media-io / yaserde

Yet Another Serializer/Deserializer
MIT License
174 stars 58 forks source link

Serialization of smart pointers #165

Open NiklasVousten opened 9 months ago

NiklasVousten commented 9 months ago

Currently yaserde has no serialization or deserialization for smart pointers. So the usage of Box, Rc, Arc is not possible.

Implementing this would allow the usage of recursive data structures

MarcAntoine-Arnaud commented 9 months ago

Good point ! We have to look on SerDe (feature rc support it)

QAQtutu commented 8 months ago

Agree, now I need an Rc<RefCell>. My solution is to create a packaging structure and implement YaDeserialize, YaSerialize, and Deref for it. This seems to work.

pub struct MultiRef<T> {
    inner: Rc<RefCell<T>>,
}

impl<T: YaDeserialize + YaSerialize> YaDeserialize for MultiRef<T> {
    fn deserialize<R: std::io::prelude::Read>(
        reader: &mut yaserde::de::Deserializer<R>,
    ) -> Result<Self, String> {
        let inner = T::deserialize(reader)?;
        Ok(Self {
            inner: Rc::new(RefCell::new(inner)),
        })
    }
}

impl<T: YaDeserialize + YaSerialize> YaSerialize for MultiRef<T> {
    fn serialize<W: std::io::prelude::Write>(
        &self,
        writer: &mut yaserde::ser::Serializer<W>,
    ) -> Result<(), String> {
        self.inner.as_ref().borrow().serialize(writer)?;
        Ok(())
    }

    fn serialize_attributes(
        &self,
        attributes: Vec<xml::attribute::OwnedAttribute>,
        namespace: xml::namespace::Namespace,
    ) -> Result<
        (
            Vec<xml::attribute::OwnedAttribute>,
            xml::namespace::Namespace,
        ),
        String,
    > {
        self.inner
            .as_ref()
            .borrow()
            .serialize_attributes(attributes, namespace)
    }
}

impl<T: YaDeserialize + YaSerialize + Default> Default for MultiRef<T> {
    fn default() -> Self {
        Self {
            inner: Default::default(),
        }
    }
}

impl<T: YaDeserialize + YaSerialize> Clone for MultiRef<T> {
    fn clone(&self) -> Self {
        Self {
            inner: self.inner.clone(),
        }
    }
}

impl<T: YaDeserialize + YaSerialize + Debug> Debug for MultiRef<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.inner.as_ref().borrow().fmt(f)
    }
}

impl<T> Deref for MultiRef<T> {
    type Target = Rc<RefCell<T>>;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}