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.
5

            
6
use std::cell::RefCell;
7
use std::rc::Rc;
8

            
9
use serde::de::Deserialize;
10
use serde::de::Error;
11
use serde::Serialize;
12
use serde_with::{DeserializeAs, SerializeAs};
13

            
14
/// A unique id, used to distinguish between objects of the same type.
15
///
16
///
17
/// This is used for pointer translation during (de)serialisation.
18
pub type ObjId = u32;
19

            
20
/// 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.
26
pub 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.
31
    fn id(&self) -> ObjId;
32
}
33

            
34
/// A type that can be created with default values and an id.
35
pub trait DefaultWithId: HasId {
36
    /// Creates a new default value of type `T`, but with the given id.
37
    fn default_with_id(id: ObjId) -> Self;
38
}
39

            
40
/// 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`].
49
pub struct RcRefCellAsId;
50

            
51
// https://docs.rs/serde_with/3.12.0/serde_with/trait.SerializeAs.html#implementing-a-converter-type
52

            
53
impl<T> SerializeAs<Rc<RefCell<T>>> for RcRefCellAsId
54
where
55
    T: HasId,
56
{
57
    fn serialize_as<S>(source: &Rc<RefCell<T>>, serializer: S) -> Result<S::Ok, S::Error>
58
    where
59
        S: serde::Serializer,
60
    {
61
        let id = (**source).borrow().id();
62
        serializer.collect_str(&id)
63
    }
64
}
65

            
66
// https://docs.rs/serde_with/3.12.0/serde_with/trait.DeserializeAs.html
67
impl<'de, T> DeserializeAs<'de, Rc<RefCell<T>>> for RcRefCellAsId
68
where
69
    T: HasId + DefaultWithId,
70
{
71
    fn deserialize_as<D>(deserializer: D) -> Result<Rc<RefCell<T>>, D::Error>
72
    where
73
        D: serde::Deserializer<'de>,
74
    {
75
        let id = u32::deserialize(deserializer).map_err(Error::custom)?;
76
        Ok(Rc::new(RefCell::new(T::default_with_id(id))))
77
    }
78
}
79

            
80
/// 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`].
87
pub struct RcRefCellAsInner;
88

            
89
impl<T> SerializeAs<Rc<RefCell<T>>> for RcRefCellAsInner
90
where
91
    T: Serialize + HasId,
92
{
93
3582
    fn serialize_as<S>(source: &Rc<RefCell<T>>, serializer: S) -> Result<S::Ok, S::Error>
94
3582
    where
95
3582
        S: serde::Serializer,
96
3582
    {
97
3582
        (**source).borrow().serialize(serializer)
98
3582
    }
99
}
100

            
101
impl<T> SerializeAs<Rc<T>> for RcRefCellAsInner
102
where
103
    T: Serialize + HasId,
104
{
105
10962
    fn serialize_as<S>(source: &Rc<T>, serializer: S) -> Result<S::Ok, S::Error>
106
10962
    where
107
10962
        S: serde::Serializer,
108
10962
    {
109
10962
        source.serialize(serializer)
110
10962
    }
111
}
112

            
113
impl<'de, T> DeserializeAs<'de, Rc<RefCell<T>>> for RcRefCellAsInner
114
where
115
    T: Deserialize<'de> + HasId + DefaultWithId,
116
{
117
2392
    fn deserialize_as<D>(deserializer: D) -> Result<Rc<RefCell<T>>, D::Error>
118
2392
    where
119
2392
        D: serde::Deserializer<'de>,
120
2392
    {
121
2392
        let val = T::deserialize(deserializer)?;
122
2392
        Ok(Rc::new(RefCell::new(val)))
123
2392
    }
124
}
125

            
126
impl<'de, T> DeserializeAs<'de, Rc<T>> for RcRefCellAsInner
127
where
128
    T: Deserialize<'de> + HasId + DefaultWithId,
129
{
130
6992
    fn deserialize_as<D>(deserializer: D) -> Result<Rc<T>, D::Error>
131
6992
    where
132
6992
        D: serde::Deserializer<'de>,
133
6992
    {
134
6992
        let val = T::deserialize(deserializer)?;
135
6992
        Ok(Rc::new(val))
136
6992
    }
137
}