intuicio_framework_serde/
lib.rs

1use intuicio_data::type_hash::TypeHash;
2use serde::{Serialize, de::DeserializeOwned};
3use std::{collections::HashMap, error::Error};
4
5pub use serde_intermediate::{
6    Intermediate, Object,
7    de::intermediate::DeserializeMode,
8    error::{Error as IntermediateError, Result as IntermediateResult},
9    from_intermediate, from_intermediate_as, from_object, from_str, from_str_as, to_intermediate,
10    to_object, to_string, to_string_compact, to_string_pretty,
11};
12
13struct Serializer {
14    #[allow(clippy::type_complexity)]
15    serialize_from: Box<dyn Fn(*const u8) -> Result<Intermediate, Box<dyn Error>> + Send + Sync>,
16    #[allow(clippy::type_complexity)]
17    deserialize_to: Box<dyn Fn(*mut u8, &Intermediate) -> Result<(), Box<dyn Error>> + Send + Sync>,
18}
19
20#[derive(Default)]
21pub struct SerializationRegistry {
22    mapping: HashMap<TypeHash, Serializer>,
23}
24
25impl SerializationRegistry {
26    pub fn with_basic_types(mut self) -> Self {
27        self.register::<()>(
28            |_| Ok(Intermediate::Unit),
29            |_, value| {
30                if matches!(value, Intermediate::Unit) {
31                    Ok(())
32                } else {
33                    Err("Expected unit value".into())
34                }
35            },
36        );
37        self.register::<bool>(
38            |data| Ok((*data).into()),
39            |data, value| {
40                if let Intermediate::Bool(value) = value {
41                    *data = *value;
42                    Ok(())
43                } else {
44                    Err("Expected bool value".into())
45                }
46            },
47        );
48        self.register::<i8>(
49            |data| Ok((*data).into()),
50            |data, value| {
51                if let Intermediate::I8(value) = value {
52                    *data = *value;
53                    Ok(())
54                } else {
55                    Err("Expected i8 value".into())
56                }
57            },
58        );
59        self.register::<i16>(
60            |data| Ok((*data).into()),
61            |data, value| match value {
62                Intermediate::I8(value) => {
63                    *data = *value as _;
64                    Ok(())
65                }
66                Intermediate::I16(value) => {
67                    *data = *value;
68                    Ok(())
69                }
70                _ => Err("Expected i16 value".into()),
71            },
72        );
73        self.register::<i32>(
74            |data| Ok((*data).into()),
75            |data, value| match value {
76                Intermediate::I8(value) => {
77                    *data = *value as _;
78                    Ok(())
79                }
80                Intermediate::I16(value) => {
81                    *data = *value as _;
82                    Ok(())
83                }
84                Intermediate::I32(value) => {
85                    *data = *value;
86                    Ok(())
87                }
88                _ => Err("Expected i32 value".into()),
89            },
90        );
91        self.register::<i64>(
92            |data| Ok((*data).into()),
93            |data, value| match value {
94                Intermediate::I8(value) => {
95                    *data = *value as _;
96                    Ok(())
97                }
98                Intermediate::I16(value) => {
99                    *data = *value as _;
100                    Ok(())
101                }
102                Intermediate::I32(value) => {
103                    *data = *value as _;
104                    Ok(())
105                }
106                Intermediate::I64(value) => {
107                    *data = *value;
108                    Ok(())
109                }
110                _ => Err("Expected i64 value".into()),
111            },
112        );
113        self.register::<i128>(
114            |data| Ok((*data).into()),
115            |data, value| match value {
116                Intermediate::I8(value) => {
117                    *data = *value as _;
118                    Ok(())
119                }
120                Intermediate::I16(value) => {
121                    *data = *value as _;
122                    Ok(())
123                }
124                Intermediate::I32(value) => {
125                    *data = *value as _;
126                    Ok(())
127                }
128                Intermediate::I64(value) => {
129                    *data = *value as _;
130                    Ok(())
131                }
132                Intermediate::I128(value) => {
133                    *data = *value;
134                    Ok(())
135                }
136                _ => Err("Expected i128 value".into()),
137            },
138        );
139        self.register::<isize>(
140            |data| Ok((*data).into()),
141            |data, value| match value {
142                Intermediate::I8(value) => {
143                    *data = *value as _;
144                    Ok(())
145                }
146                Intermediate::I16(value) => {
147                    *data = *value as _;
148                    Ok(())
149                }
150                Intermediate::I32(value) => {
151                    *data = *value as _;
152                    Ok(())
153                }
154                Intermediate::I64(value) => {
155                    *data = *value as _;
156                    Ok(())
157                }
158                _ => Err("Expected isize value".into()),
159            },
160        );
161        self.register::<u8>(
162            |data| Ok((*data).into()),
163            |data, value| {
164                if let Intermediate::U8(value) = value {
165                    *data = *value;
166                    Ok(())
167                } else {
168                    Err("Expected u8 value".into())
169                }
170            },
171        );
172        self.register::<u16>(
173            |data| Ok((*data).into()),
174            |data, value| match value {
175                Intermediate::U8(value) => {
176                    *data = *value as _;
177                    Ok(())
178                }
179                Intermediate::U16(value) => {
180                    *data = *value;
181                    Ok(())
182                }
183                _ => Err("Expected u16 value".into()),
184            },
185        );
186        self.register::<u32>(
187            |data| Ok((*data).into()),
188            |data, value| match value {
189                Intermediate::U8(value) => {
190                    *data = *value as _;
191                    Ok(())
192                }
193                Intermediate::U16(value) => {
194                    *data = *value as _;
195                    Ok(())
196                }
197                Intermediate::U32(value) => {
198                    *data = *value;
199                    Ok(())
200                }
201                _ => Err("Expected u32 value".into()),
202            },
203        );
204        self.register::<u64>(
205            |data| Ok((*data).into()),
206            |data, value| match value {
207                Intermediate::U8(value) => {
208                    *data = *value as _;
209                    Ok(())
210                }
211                Intermediate::U16(value) => {
212                    *data = *value as _;
213                    Ok(())
214                }
215                Intermediate::U32(value) => {
216                    *data = *value as _;
217                    Ok(())
218                }
219                Intermediate::U64(value) => {
220                    *data = *value;
221                    Ok(())
222                }
223                _ => Err("Expected u64 value".into()),
224            },
225        );
226        self.register::<u128>(
227            |data| Ok((*data).into()),
228            |data, value| match value {
229                Intermediate::U8(value) => {
230                    *data = *value as _;
231                    Ok(())
232                }
233                Intermediate::U16(value) => {
234                    *data = *value as _;
235                    Ok(())
236                }
237                Intermediate::U32(value) => {
238                    *data = *value as _;
239                    Ok(())
240                }
241                Intermediate::U64(value) => {
242                    *data = *value as _;
243                    Ok(())
244                }
245                Intermediate::U128(value) => {
246                    *data = *value;
247                    Ok(())
248                }
249                _ => Err("Expected u128 value".into()),
250            },
251        );
252        self.register::<usize>(
253            |data| Ok((*data).into()),
254            |data, value| match value {
255                Intermediate::U8(value) => {
256                    *data = *value as _;
257                    Ok(())
258                }
259                Intermediate::U16(value) => {
260                    *data = *value as _;
261                    Ok(())
262                }
263                Intermediate::U32(value) => {
264                    *data = *value as _;
265                    Ok(())
266                }
267                Intermediate::U64(value) => {
268                    *data = *value as _;
269                    Ok(())
270                }
271                _ => Err("Expected usize value".into()),
272            },
273        );
274        self.register::<f32>(
275            |data| Ok((*data).into()),
276            |data, value| match value {
277                Intermediate::I8(value) => {
278                    *data = *value as _;
279                    Ok(())
280                }
281                Intermediate::I16(value) => {
282                    *data = *value as _;
283                    Ok(())
284                }
285                Intermediate::I32(value) => {
286                    *data = *value as _;
287                    Ok(())
288                }
289                Intermediate::U8(value) => {
290                    *data = *value as _;
291                    Ok(())
292                }
293                Intermediate::U16(value) => {
294                    *data = *value as _;
295                    Ok(())
296                }
297                Intermediate::U32(value) => {
298                    *data = *value as _;
299                    Ok(())
300                }
301                Intermediate::F32(value) => {
302                    *data = *value;
303                    Ok(())
304                }
305                _ => Err("Expected f32 value".into()),
306            },
307        );
308        self.register::<f64>(
309            |data| Ok((*data).into()),
310            |data, value| match value {
311                Intermediate::I8(value) => {
312                    *data = *value as _;
313                    Ok(())
314                }
315                Intermediate::I16(value) => {
316                    *data = *value as _;
317                    Ok(())
318                }
319                Intermediate::I32(value) => {
320                    *data = *value as _;
321                    Ok(())
322                }
323                Intermediate::I64(value) => {
324                    *data = *value as _;
325                    Ok(())
326                }
327                Intermediate::U8(value) => {
328                    *data = *value as _;
329                    Ok(())
330                }
331                Intermediate::U16(value) => {
332                    *data = *value as _;
333                    Ok(())
334                }
335                Intermediate::U32(value) => {
336                    *data = *value as _;
337                    Ok(())
338                }
339                Intermediate::U64(value) => {
340                    *data = *value as _;
341                    Ok(())
342                }
343                Intermediate::F32(value) => {
344                    *data = *value as _;
345                    Ok(())
346                }
347                Intermediate::F64(value) => {
348                    *data = *value;
349                    Ok(())
350                }
351                _ => Err("Expected f64 value".into()),
352            },
353        );
354        self.register::<char>(
355            |data| Ok((*data).into()),
356            |data, value| match value {
357                Intermediate::Char(value) => {
358                    *data = *value;
359                    Ok(())
360                }
361                Intermediate::String(value) => {
362                    if let Some(value) = value.chars().next() {
363                        *data = value;
364                        Ok(())
365                    } else {
366                        Err("Expected char value (intermediate string is empty)".into())
367                    }
368                }
369                _ => Err("Expected char value".into()),
370            },
371        );
372        self.register::<String>(
373            |data| Ok(data.as_str().into()),
374            |data, value| {
375                if let Intermediate::String(value) = value {
376                    *data = value.to_owned();
377                    Ok(())
378                } else {
379                    Err("Expected string value".into())
380                }
381            },
382        );
383        self
384    }
385
386    pub fn with_serde<T: Serialize + DeserializeOwned>(mut self) -> Self {
387        self.register_serde::<T>();
388        self
389    }
390
391    pub fn register_serde<T: Serialize + DeserializeOwned>(&mut self) {
392        self.register::<T>(
393            |data| Ok(serde_intermediate::to_intermediate(data)?),
394            |data, value| {
395                *data = serde_intermediate::from_intermediate(value)?;
396                Ok(())
397            },
398        );
399    }
400
401    pub fn register<T>(
402        &mut self,
403        serialize_from: impl Fn(&T) -> Result<Intermediate, Box<dyn Error>> + Send + Sync + 'static,
404        deserialize_to: impl Fn(&mut T, &Intermediate) -> Result<(), Box<dyn Error>>
405        + Send
406        + Sync
407        + 'static,
408    ) {
409        unsafe {
410            self.register_raw(
411                TypeHash::of::<T>(),
412                move |data| serialize_from(data.cast::<T>().as_ref().unwrap()),
413                move |data, value| deserialize_to(data.cast::<T>().as_mut().unwrap(), value),
414            );
415        }
416    }
417
418    /// # Safety
419    pub unsafe fn register_raw(
420        &mut self,
421        type_hash: TypeHash,
422        serialize_from: impl Fn(*const u8) -> Result<Intermediate, Box<dyn Error>>
423        + Send
424        + Sync
425        + 'static,
426        deserialize_to: impl Fn(*mut u8, &Intermediate) -> Result<(), Box<dyn Error>>
427        + Send
428        + Sync
429        + 'static,
430    ) {
431        self.mapping.insert(
432            type_hash,
433            Serializer {
434                serialize_from: Box::new(serialize_from),
435                deserialize_to: Box::new(deserialize_to),
436            },
437        );
438    }
439
440    pub fn unregister<T>(&mut self) {
441        self.unregister_raw(TypeHash::of::<T>());
442    }
443
444    pub fn unregister_raw(&mut self, type_hash: TypeHash) {
445        self.mapping.remove(&type_hash);
446    }
447
448    pub fn serialize_from<T>(&self, data: &T) -> Result<Intermediate, Box<dyn Error>> {
449        unsafe { self.dynamic_serialize_from(TypeHash::of::<T>(), data as *const T as *const u8) }
450    }
451
452    /// # Safety
453    pub unsafe fn dynamic_serialize_from(
454        &self,
455        type_hash: TypeHash,
456        data: *const u8,
457    ) -> Result<Intermediate, Box<dyn Error>> {
458        if let Some(serializer) = self.mapping.get(&type_hash) {
459            return (serializer.serialize_from)(data);
460        }
461        Err("Type not existent in serialization registry".into())
462    }
463
464    pub fn deserialize_to<T: Default>(&self, value: &Intermediate) -> Result<T, Box<dyn Error>> {
465        let mut result = T::default();
466        unsafe {
467            self.dynamic_deserialize_to(
468                TypeHash::of::<T>(),
469                &mut result as *mut T as *mut u8,
470                value,
471            )?;
472        }
473        Ok(result)
474    }
475
476    /// # Safety
477    pub unsafe fn dynamic_deserialize_to(
478        &self,
479        type_hash: TypeHash,
480        data: *mut u8,
481        value: &Intermediate,
482    ) -> Result<(), Box<dyn Error>> {
483        if let Some(serializer) = self.mapping.get(&type_hash) {
484            (serializer.deserialize_to)(data, value)?;
485            return Ok(());
486        }
487        Err("Type not existent in serialization registry".into())
488    }
489}
490
491#[cfg(test)]
492mod tests {
493    use super::*;
494    use intuicio_derive::{IntuicioEnum, IntuicioStruct};
495    use serde::Deserialize;
496
497    #[derive(IntuicioEnum, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
498    #[repr(u8)]
499    enum Skill {
500        #[default]
501        Brain,
502        Muscles(bool),
503        Magic {
504            power: i32,
505        },
506    }
507
508    #[derive(IntuicioStruct, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
509    struct Person {
510        name: String,
511        age: usize,
512        skill: Skill,
513    }
514
515    #[test]
516    fn test_serialization() {
517        let serialization = SerializationRegistry::default()
518            .with_basic_types()
519            .with_serde::<Skill>()
520            .with_serde::<Person>();
521
522        let person = Person {
523            name: "Grumpy".to_owned(),
524            age: 24,
525            skill: Skill::Magic { power: 42 },
526        };
527        let serialized = serialization.serialize_from(&person).unwrap();
528        let person2 = serialization.deserialize_to::<Person>(&serialized).unwrap();
529        assert_eq!(person, person2);
530    }
531}