conjure_cp_core/ast/declaration/
serde.rs

1use std::cell::RefCell;
2
3use crate::ast::serde::DefaultWithId;
4use crate::ast::{Name, serde::HasId};
5use serde::Deserialize;
6use serde::Serialize;
7use serde_with::{DeserializeAs, SerializeAs};
8
9use super::{Declaration, DeclarationKind, DeclarationPtr, DeclarationPtrInner};
10
11/// (De)serializes a [`DeclarationPtr`] as its id.
12///
13/// On deserialization, each declaration is re-created with default dummy values, except for the
14/// id, which will be the same as the original declaration.
15///
16/// It is left to the user to fix these values before use. Before serialization, each object in
17/// memory has a unique id; using this information, re-constructing the shared pointers should be
18/// possible, as long as the contents of each object were also stored, e.g. with [`DeclarationPtrFull`].
19///
20/// # Examples
21///
22/// Serialisation:
23///
24/// ```
25/// use serde::Serialize;
26/// use serde_json::json;
27/// use serde_with::serde_as;
28/// use conjure_cp_core::ast::{declaration::serde::DeclarationPtrAsId,Name,DeclarationPtr,Domain,Range};
29///
30/// // some struct containing a DeclarationPtr.
31/// #[serde_as]
32/// #[derive(Clone,PartialEq,Eq,Serialize)]
33/// struct Foo {
34///     #[serde_as(as = "DeclarationPtrAsId")]
35///     declaration: DeclarationPtr,
36///
37///     // serde as also supports nesting
38///     #[serde_as(as = "Vec<(_,DeclarationPtrAsId)>")]
39///     declarations: Vec<(i32,DeclarationPtr)>,
40///
41///     c: i32
42/// }
43///
44/// let declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::Int(vec![Range::Bounded(1,5)]));
45/// let mut declarations: Vec<(i32,DeclarationPtr)>  = vec![];
46/// for i in (1..=2) {
47///     declarations.push((i,DeclarationPtr::new_var(Name::User(format!("{i}").into()),Domain::Int(vec![Range::Bounded(1,5)]))));
48/// }
49///
50/// let foo = Foo {
51///     declaration,
52///     declarations,
53///     c: 3
54/// };
55///
56/// let json = serde_json::to_value(foo).unwrap();
57///
58/// let expected_json = json!({
59///     "declaration": 0,
60///     "declarations": [(1,1),(2,2)],
61///     "c": 3
62/// });
63///
64/// assert_eq!(json,expected_json);
65/// ```
66///
67/// Deserialisation:
68///
69/// ```
70/// use serde::Deserialize;
71/// use serde_json::json;
72/// use serde_with::serde_as;
73/// use conjure_cp_core::ast::{serde::{HasId},declaration::serde::DeclarationPtrAsId,Name,DeclarationKind, DeclarationPtr,Domain,Range, ReturnType};
74///
75/// // some struct containing a DeclarationPtr.
76/// #[serde_as]
77/// #[derive(Clone,PartialEq,Eq,Deserialize)]
78/// struct Foo {
79///     #[serde_as(as = "DeclarationPtrAsId")]
80///     declaration: DeclarationPtr,
81///
82///     // serde as also supports nesting
83///     #[serde_as(as = "Vec<(_,DeclarationPtrAsId)>")]
84///     declarations: Vec<(i32,DeclarationPtr)>,
85///     c: i32
86/// }
87///
88/// let input_json = json!({
89///     "declaration": 10,
90///     "declarations": [(11,11),(12,12)],
91///     "c": 3
92/// });
93///
94///
95/// let foo: Foo = serde_json::from_value(input_json).unwrap();
96///
97///
98/// // all declarations should have the dummy values: name: User("_UNKNOWN"), kind: value_letting;
99/// assert_eq!(&foo.declaration.name() as &Name,&Name::User("_UNKNOWN".into()));
100/// assert_eq!(&foo.declarations[0].1.name() as &Name,&Name::User("_UNKNOWN".into()));
101/// assert_eq!(&foo.declarations[1].1.name() as &Name,&Name::User("_UNKNOWN".into()));
102///
103/// assert!(matches!(&foo.declaration.kind() as &DeclarationKind,&DeclarationKind::ValueLetting(_)));
104/// assert!(matches!(&foo.declarations[0].1.kind() as &DeclarationKind,&DeclarationKind::ValueLetting(_)));
105/// assert!(matches!(&foo.declarations[1].1.kind() as &DeclarationKind,&DeclarationKind::ValueLetting(_)));
106///
107/// // but ids should be the same
108///
109/// assert_eq!(*&foo.declaration.id(),10);
110/// assert_eq!(*&foo.declarations[0].1.id(),11);
111/// assert_eq!(*&foo.declarations[1].1.id(),12);
112/// ```
113///
114pub struct DeclarationPtrAsId;
115
116impl SerializeAs<DeclarationPtr> for DeclarationPtrAsId {
117    fn serialize_as<S>(source: &DeclarationPtr, serializer: S) -> Result<S::Ok, S::Error>
118    where
119        S: serde::Serializer,
120    {
121        let id = source.id();
122        serializer.serialize_u32(id)
123    }
124}
125
126impl<'de> DeserializeAs<'de, DeclarationPtr> for DeclarationPtrAsId {
127    fn deserialize_as<D>(deserializer: D) -> Result<DeclarationPtr, D::Error>
128    where
129        D: serde::Deserializer<'de>,
130    {
131        let id = u32::deserialize(deserializer)?;
132        Ok(DeclarationPtr::default_with_id(id))
133    }
134}
135
136/// (De)serializes a [`DeclarationPtr`] as the declaration it references.
137///
138/// This makes no attempt to restore the pointers - each value is deserialized into a new
139/// `DeclarationPtr` with a reference count of one.
140///
141/// The shared references can be reconstructed using the ids stored, as before serialization these
142/// were unique for each separate instance of `T` in memory. See [`DeclarationPtrAsId`].
143///
144/// # Examples
145///
146/// Serialisation:
147///
148/// ```
149/// use serde::Serialize;
150/// use serde_json::json;
151/// use serde_with::serde_as;
152/// use conjure_cp_core::ast::{declaration::serde::DeclarationPtrFull,Name,DeclarationPtr,Domain,Range};
153///
154/// // some struct containing a DeclarationPtr.
155/// #[serde_as]
156/// #[derive(Clone,PartialEq,Eq,Serialize)]
157/// struct Foo {
158///     #[serde_as(as = "DeclarationPtrFull")]
159///     declaration: DeclarationPtr,
160///
161///     // serde as also supports nesting
162///     #[serde_as(as = "Vec<(_,DeclarationPtrFull)>")]
163///     declarations: Vec<(i32,DeclarationPtr)>,
164///
165///     c: i32
166/// }
167///
168/// let declaration = DeclarationPtr::new_var(Name::User("a".into()),Domain::Int(vec![Range::Bounded(1,5)]));
169/// let mut declarations = vec![];
170///
171/// for i in (1..=2) {
172///     let d = DeclarationPtr::new_var(Name::User(format!("{i}").into()),Domain::Int(vec![Range::Bounded(1,5)]));
173///     declarations.push((i,d));
174/// }
175///
176/// let foo = Foo {
177///     declaration,
178///     declarations,
179///     c: 3
180/// };
181///
182/// let json = serde_json::to_value(foo).unwrap();
183///
184/// let expected_json = json!({
185///     "declaration": {
186///         "name": { "User": "a"},
187///         "kind": {"DecisionVariable": {"domain": {"Int": [{"Bounded": [1,5]}]}, "category":
188///         "Decision"}},
189///         "id": 0
190///     },
191///
192///     "declarations": [
193///         [1,{
194///         "name": { "User": "1"},
195///         "id": 1,
196///         "kind": {"DecisionVariable": {"domain": {"Int": [{"Bounded": [1,5]}]},
197///         "category":"Decision"}},
198///         }],
199///         [2,{
200///         "name": { "User": "2"},
201///         "id": 2,
202///         "kind": {"DecisionVariable": {"domain": {"Int": [{"Bounded": [1,5]}]},"category":
203///         "Decision"}},
204///         }]
205///     ],
206///         
207///     "c": 3
208/// });
209///
210/// assert_eq!(json,expected_json);
211/// ```
212///
213/// Deserialisation:
214///
215/// ```
216/// use serde::Deserialize;
217/// use serde_json::json;
218/// use serde_with::serde_as;
219/// use conjure_cp_core::ast::{serde::{HasId},declaration::serde::DeclarationPtrFull,Name,DeclarationKind, DeclarationPtr,Domain,Range, ReturnType};
220///
221/// // some struct containing a DeclarationPtr.
222/// #[serde_as]
223/// #[derive(Clone,PartialEq,Eq,Deserialize)]
224/// struct Foo {
225///     #[serde_as(as = "DeclarationPtrFull")]
226///     declaration: DeclarationPtr,
227///
228///     // serde as also supports nesting
229///     #[serde_as(as = "Vec<(_,DeclarationPtrFull)>")]
230///     declarations: Vec<(i32,DeclarationPtr)>,
231///     c: i32
232/// }
233///
234/// let input_json = json!({
235///     "declaration": {
236///         "name": { "User": "a"},
237///         "kind": {"DecisionVariable": {"domain": {"Int": [{"Bounded": [0,5]}]}, "category":
238///         "Decision"}},
239///         "id": 10,
240///     },
241///
242///     "declarations": [
243///         [1,{
244///         "name": { "User": "1"},
245///         "kind": {"DecisionVariable": {"domain": {"Int": [{"Bounded": [0,5]}]}, "category":
246///         "Decision"}},
247///         "id": 11,
248///         }],
249///         [2,{
250///         "name": { "User": "2"},
251///         "kind": {"DecisionVariable": {"domain": {"Int": [{"Bounded": [0,5]}]}, "category":
252///         "Decision"}},
253///         "id": 12,
254///         }]
255///     ],
256///     "c": 3
257/// });
258///
259///
260/// let foo: Foo = serde_json::from_value(input_json).unwrap();
261///
262/// assert_eq!(&foo.declaration.name() as &Name,&Name::User("a".into()));
263/// assert_eq!(&foo.declarations[0].1.name() as &Name,&Name::User("1".into()));
264/// assert_eq!(&foo.declarations[1].1.name() as &Name,&Name::User("2".into()));
265///
266/// assert!(matches!(&foo.declaration.kind() as &DeclarationKind,&DeclarationKind::DecisionVariable(_)));
267/// assert!(matches!(&foo.declarations[0].1.kind() as &DeclarationKind,&DeclarationKind::DecisionVariable(_)));
268/// assert!(matches!(&foo.declarations[1].1.kind() as &DeclarationKind,&DeclarationKind::DecisionVariable(_)));
269///
270/// // ids should be the same as in the json
271/// assert_eq!(*&foo.declaration.id(),10);
272/// assert_eq!(*&foo.declarations[0].1.id(),11);
273/// assert_eq!(*&foo.declarations[1].1.id(),12);
274/// ```
275pub struct DeclarationPtrFull;
276
277// temporary structs to put things in the right format befo:re we (de)serialize
278//
279// this is a bit of a hack to get around the nested types in declarationPtr.
280#[derive(Serialize)]
281struct DeclarationSe<'a> {
282    name: &'a Name,
283    kind: &'a DeclarationKind,
284    id: u32,
285}
286
287#[derive(Deserialize)]
288struct DeclarationDe {
289    name: Name,
290    kind: DeclarationKind,
291    id: u32,
292}
293
294impl SerializeAs<DeclarationPtr> for DeclarationPtrFull {
295    fn serialize_as<S>(source: &DeclarationPtr, serializer: S) -> Result<S::Ok, S::Error>
296    where
297        S: serde::Serializer,
298    {
299        let id = source.id();
300        let decl: &Declaration = &source.borrow();
301        let x = DeclarationSe {
302            name: &decl.name,
303            kind: &decl.kind,
304            id,
305        };
306
307        x.serialize(serializer)
308    }
309}
310
311impl<'de> DeserializeAs<'de, DeclarationPtr> for DeclarationPtrFull {
312    fn deserialize_as<D>(deserializer: D) -> Result<DeclarationPtr, D::Error>
313    where
314        D: serde::Deserializer<'de>,
315    {
316        let x = DeclarationDe::deserialize(deserializer)?;
317        Ok(DeclarationPtr {
318            inner: DeclarationPtrInner::new_with_id_unchecked(
319                RefCell::new(Declaration::new(x.name, x.kind)),
320                x.id,
321            ),
322        })
323    }
324}