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}