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}