Skip to main content

conjure_cp_core/ast/declaration/
serde.rs

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