use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub mod smart_ptr {
use super::*;
use std::{ops::Deref, rc::Rc, sync::Arc};
pub trait SmartPtr: Deref {
fn new(inner: Self::Target) -> Self;
}
macro_rules! impl_smart_ptr {
($ptr:ident) => {
impl<T> SmartPtr for $ptr<T> {
fn new(inner: Self::Target) -> Self {
$ptr::new(inner)
}
}
};
}
impl_smart_ptr!(Arc);
impl_smart_ptr!(Box);
impl_smart_ptr!(Rc);
pub fn serialize<P, T, S>(field: &P, ser: S) -> Result<S::Ok, S::Error>
where
P: SmartPtr<Target = T>,
T: ?Sized + Serialize,
S: Serializer,
{
field.deref().serialize(ser)
}
pub fn deserialize<'de, P, T, D>(de: D) -> Result<P, D::Error>
where
P: SmartPtr<Target = T>,
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<P: SmartPtr<Target = String>> {
#[serde(with = "smart_ptr")]
field: P,
}
impl<P: SmartPtr<Target = String>> Test<P> {
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<String>> = from_vec(&to_vec(&expected).unwrap()).unwrap();
assert_eq!(expected, actual);
}
}
};
}
check_ptr!(Arc);
check_ptr!(Box);
check_ptr!(Rc);
}