//! Modules that help with serializing and deserializing struct fields via the //! `#[serde(with ="path")]` attribute. use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// A helper for serializing and deserializing fields which are "smart pointers", types like /// [std::sync::Arc], [std::rc::Rc], and [Box]. pub mod smart_ptr { use super::*; use std::{ops::Deref, rc::Rc, sync::Arc}; /// Trait for general smart pointers. pub trait SmartPtr: Deref { /// Creates a new pointer which points to the given target. fn new(inner: Self::Target) -> Self; } macro_rules! impl_smart_ptr { ($ptr:ident) => { impl SmartPtr for $ptr { fn new(inner: Self::Target) -> Self { $ptr::new(inner) } } }; } impl_smart_ptr!(Arc); impl_smart_ptr!(Box); impl_smart_ptr!(Rc); pub fn serialize(field: &P, ser: S) -> Result where P: SmartPtr, T: ?Sized + Serialize, S: Serializer, { field.deref().serialize(ser) } pub fn deserialize<'de, P, T, D>(de: D) -> Result where P: SmartPtr, T: ?Sized + Deserialize<'de>, D: Deserializer<'de>, { Ok(P::new(T::deserialize(de)?)) } } #[cfg(test)] mod smart_ptr_tests { use crate::{from_vec, to_vec}; use paste::paste; use serde::{Deserialize, Serialize}; use std::{rc::Rc, sync::Arc}; use super::smart_ptr::{self, SmartPtr}; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] struct Test> { #[serde(with = "smart_ptr")] field: P, } impl> Test

{ fn new(expected: &str) -> Self { Test { field: P::new(expected.to_string()), } } } macro_rules! check_ptr { ($ptr:ty) => { paste! { #[test] fn [<"check_" $ptr:lower>]() { let expected = Test::new("expected"); let actual: Test<$ptr> = from_vec(&to_vec(&expected).unwrap()).unwrap(); assert_eq!(expected, actual); } } }; } check_ptr!(Arc); check_ptr!(Box); check_ptr!(Rc); }