1//! Serde serialization/ deserialization helpers.
2//!
3//! These are used in combination with the
4//! [`serde_as`](https://docs.rs/serde_with/3.12.0/serde_with/index.html) annotation on AST types.
56use std::cell::RefCell;
7use std::rc::Rc;
89use serde::de::Deserialize;
10use serde::de::Error;
11use serde::Serialize;
12use serde_with::{DeserializeAs, SerializeAs};
1314/// A unique id, used to distinguish between objects of the same type.
15///
16///
17/// This is used for pointer translation during (de)serialisation.
18pub type ObjId = u32;
1920/// A type with an [`ObjectId`].
21///
22/// Each object of the implementing type has a unique id; however, ids are not unique for different
23/// type of objects.
24///
25/// Implementing types should ensure that the id is updated when an object is cloned.
26pub trait HasId {
27/// The id of this object.
28 ///
29 /// Each object of this type has a unique id; however, ids are not unique for different type of
30 /// objects.
31fn id(&self) -> ObjId;
32}
3334/// A type that can be created with default values and an id.
35pub trait DefaultWithId: HasId {
36/// Creates a new default value of type `T`, but with the given id.
37fn default_with_id(id: ObjId) -> Self;
38}
3940/// De/Serialize an `Rc<RefCell<T>>` as the id of the inner value `T`.
41///
42/// On de-serialization, each object is created as the default value for that type, except with the
43/// id's being retained.
44///
45/// It is left to the user to fix these values before use. Before serialization, each object in
46/// memory has a unique id; using this information, re-constructing the shared pointers should be
47/// possible, as long as the contents of each object were also stored, e.g. with
48/// [`RcRefCellAsInner`].
49pub struct RcRefCellAsId;
5051// https://docs.rs/serde_with/3.12.0/serde_with/trait.SerializeAs.html#implementing-a-converter-type
5253impl<T> SerializeAs<Rc<RefCell<T>>> for RcRefCellAsId
54where
55T: HasId,
56{
57fn serialize_as<S>(source: &Rc<RefCell<T>>, serializer: S) -> Result<S::Ok, S::Error>
58where
59S: serde::Serializer,
60 {
61let id = (**source).borrow().id();
62 serializer.serialize_u32(id)
63 }
64}
6566// https://docs.rs/serde_with/3.12.0/serde_with/trait.DeserializeAs.html
67impl<'de, T> DeserializeAs<'de, Rc<RefCell<T>>> for RcRefCellAsId
68where
69T: HasId + DefaultWithId,
70{
71fn deserialize_as<D>(deserializer: D) -> Result<Rc<RefCell<T>>, D::Error>
72where
73D: serde::Deserializer<'de>,
74 {
75let id = u32::deserialize(deserializer).map_err(Error::custom)?;
76Ok(Rc::new(RefCell::new(T::default_with_id(id))))
77 }
78}
7980/// De/Serialize an `Rc<RefCell<T>>` as its inner value `T`.
81///
82/// This makes no attempt to restore the pointers - each value is de-serialized into a new
83/// Rc<RefCell<T>> with a reference count of one.
84///
85/// The shared references can be reconstructed using the ids stored, as before serialization these
86/// were unique for each separate instance of `T` in memory. See [`RcRefCellAsId`].
87pub struct RcRefCellAsInner;
8889impl<T> SerializeAs<Rc<RefCell<T>>> for RcRefCellAsInner
90where
91T: Serialize + HasId,
92{
93fn serialize_as<S>(source: &Rc<RefCell<T>>, serializer: S) -> Result<S::Ok, S::Error>
94where
95S: serde::Serializer,
96 {
97 (**source).borrow().serialize(serializer)
98 }
99}
100101impl<T> SerializeAs<Rc<T>> for RcRefCellAsInner
102where
103T: Serialize + HasId,
104{
105fn serialize_as<S>(source: &Rc<T>, serializer: S) -> Result<S::Ok, S::Error>
106where
107S: serde::Serializer,
108 {
109 source.serialize(serializer)
110 }
111}
112113impl<'de, T> DeserializeAs<'de, Rc<RefCell<T>>> for RcRefCellAsInner
114where
115T: Deserialize<'de> + HasId + DefaultWithId,
116{
117fn deserialize_as<D>(deserializer: D) -> Result<Rc<RefCell<T>>, D::Error>
118where
119D: serde::Deserializer<'de>,
120 {
121let val = T::deserialize(deserializer)?;
122Ok(Rc::new(RefCell::new(val)))
123 }
124}
125126impl<'de, T> DeserializeAs<'de, Rc<T>> for RcRefCellAsInner
127where
128T: Deserialize<'de> + HasId + DefaultWithId,
129{
130fn deserialize_as<D>(deserializer: D) -> Result<Rc<T>, D::Error>
131where
132D: serde::Deserializer<'de>,
133 {
134let val = T::deserialize(deserializer)?;
135Ok(Rc::new(val))
136 }
137}