1
use std::cell::RefCell;
2

            
3
use crate::ast::serde::DefaultWithId;
4
use crate::ast::{Name, serde::HasId};
5
use serde::Deserialize;
6
use serde::Serialize;
7
use serde_with::{DeserializeAs, SerializeAs};
8

            
9
use 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
///
114
pub struct DeclarationPtrAsId;
115

            
116
impl 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

            
126
impl<'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": { "Ground": {"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": { "Ground": {"Int": [{"Bounded": [1,5]}]}},
197
///         "category":"Decision"}},
198
///         }],
199
///         [2,{
200
///         "name": { "User": "2"},
201
///         "id": 2,
202
///         "kind": {"DecisionVariable": {"domain": { "Ground": {"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": {"Ground": {"Int": [{"Bounded": [0,5]}]}}, "category":
238
///         "Decision"}},
239
///         "id": 10,
240
///     },
241
///
242
///     "declarations": [
243
///         [1,{
244
///         "name": { "User": "1"},
245
///         "kind": {"DecisionVariable": {"domain": {"Ground": {"Int": [{"Bounded": [0,5]}]}}, "category":
246
///         "Decision"}},
247
///         "id": 11,
248
///         }],
249
///         [2,{
250
///         "name": { "User": "2"},
251
///         "kind": {"DecisionVariable": {"domain": {"Ground": {"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
/// ```
275
pub 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)]
281
struct DeclarationSe<'a> {
282
    name: &'a Name,
283
    kind: &'a DeclarationKind,
284
    id: u32,
285
}
286

            
287
#[derive(Deserialize)]
288
struct DeclarationDe {
289
    name: Name,
290
    kind: DeclarationKind,
291
    id: u32,
292
}
293

            
294
impl 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

            
311
impl<'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
}