intuicio_framework_serde/
lib.rs

1use intuicio_core::{
2    object::Object as CoreObject,
3    registry::Registry,
4    types::{
5        EnumVariantQuery, Type, TypeHandle, TypeQuery, enum_type::Enum, struct_type::StructField,
6    },
7};
8use intuicio_data::{
9    Finalize, managed::DynamicManaged, managed_box::DynamicManagedBox, type_hash::TypeHash,
10};
11use serde::{Serialize, de::DeserializeOwned};
12use std::{collections::HashMap, error::Error};
13
14pub use serde_intermediate::{
15    Intermediate, Object,
16    de::intermediate::DeserializeMode,
17    error::{Error as IntermediateError, Result as IntermediateResult},
18    from_intermediate, from_intermediate_as, from_object, from_str, from_str_as, to_intermediate,
19    to_object, to_string, to_string_compact, to_string_pretty,
20};
21
22struct Serializer {
23    #[allow(clippy::type_complexity)]
24    serialize_from: Box<
25        dyn Fn(*const u8, &SerializationRegistry, &Registry) -> Result<Intermediate, Box<dyn Error>>
26            + Send
27            + Sync,
28    >,
29    #[allow(clippy::type_complexity)]
30    deserialize_to: Box<
31        dyn Fn(
32                *mut u8,
33                &Intermediate,
34                &SerializationRegistry,
35                bool,
36                &Registry,
37            ) -> Result<(), Box<dyn Error>>
38            + Send
39            + Sync,
40    >,
41}
42
43#[derive(Default)]
44pub struct SerializationRegistry {
45    mapping: HashMap<TypeHash, Serializer>,
46}
47
48impl SerializationRegistry {
49    pub fn with_basic_types(mut self) -> Self {
50        self.register::<()>(
51            |_, _, _| Ok(Intermediate::Unit),
52            |_, value, _, _, _| {
53                if matches!(value, Intermediate::Unit) {
54                    Ok(())
55                } else {
56                    Err("Expected unit value".into())
57                }
58            },
59        );
60        self.register::<bool>(
61            |data, _, _| Ok((*data).into()),
62            |data, value, _, _, _| {
63                if let Intermediate::Bool(value) = value {
64                    *data = *value;
65                    Ok(())
66                } else {
67                    Err("Expected bool value".into())
68                }
69            },
70        );
71        self.register::<i8>(
72            |data, _, _| Ok((*data).into()),
73            |data, value, _, _, _| {
74                if let Intermediate::I8(value) = value {
75                    *data = *value;
76                    Ok(())
77                } else {
78                    Err("Expected i8 value".into())
79                }
80            },
81        );
82        self.register::<i16>(
83            |data, _, _| Ok((*data).into()),
84            |data, value, _, _, _| match value {
85                Intermediate::I8(value) => {
86                    *data = *value as _;
87                    Ok(())
88                }
89                Intermediate::I16(value) => {
90                    *data = *value;
91                    Ok(())
92                }
93                _ => Err("Expected i16 value".into()),
94            },
95        );
96        self.register::<i32>(
97            |data, _, _| Ok((*data).into()),
98            |data, value, _, _, _| match value {
99                Intermediate::I8(value) => {
100                    *data = *value as _;
101                    Ok(())
102                }
103                Intermediate::I16(value) => {
104                    *data = *value as _;
105                    Ok(())
106                }
107                Intermediate::I32(value) => {
108                    *data = *value;
109                    Ok(())
110                }
111                _ => Err("Expected i32 value".into()),
112            },
113        );
114        self.register::<i64>(
115            |data, _, _| Ok((*data).into()),
116            |data, value, _, _, _| match value {
117                Intermediate::I8(value) => {
118                    *data = *value as _;
119                    Ok(())
120                }
121                Intermediate::I16(value) => {
122                    *data = *value as _;
123                    Ok(())
124                }
125                Intermediate::I32(value) => {
126                    *data = *value as _;
127                    Ok(())
128                }
129                Intermediate::I64(value) => {
130                    *data = *value;
131                    Ok(())
132                }
133                _ => Err("Expected i64 value".into()),
134            },
135        );
136        self.register::<i128>(
137            |data, _, _| Ok((*data).into()),
138            |data, value, _, _, _| match value {
139                Intermediate::I8(value) => {
140                    *data = *value as _;
141                    Ok(())
142                }
143                Intermediate::I16(value) => {
144                    *data = *value as _;
145                    Ok(())
146                }
147                Intermediate::I32(value) => {
148                    *data = *value as _;
149                    Ok(())
150                }
151                Intermediate::I64(value) => {
152                    *data = *value as _;
153                    Ok(())
154                }
155                Intermediate::I128(value) => {
156                    *data = *value;
157                    Ok(())
158                }
159                _ => Err("Expected i128 value".into()),
160            },
161        );
162        self.register::<isize>(
163            |data, _, _| Ok((*data).into()),
164            |data, value, _, _, _| match value {
165                Intermediate::I8(value) => {
166                    *data = *value as _;
167                    Ok(())
168                }
169                Intermediate::I16(value) => {
170                    *data = *value as _;
171                    Ok(())
172                }
173                Intermediate::I32(value) => {
174                    *data = *value as _;
175                    Ok(())
176                }
177                Intermediate::I64(value) => {
178                    *data = *value as _;
179                    Ok(())
180                }
181                _ => Err("Expected isize value".into()),
182            },
183        );
184        self.register::<u8>(
185            |data, _, _| Ok((*data).into()),
186            |data, value, _, _, _| {
187                if let Intermediate::U8(value) = value {
188                    *data = *value;
189                    Ok(())
190                } else {
191                    Err("Expected u8 value".into())
192                }
193            },
194        );
195        self.register::<u16>(
196            |data, _, _| Ok((*data).into()),
197            |data, value, _, _, _| match value {
198                Intermediate::U8(value) => {
199                    *data = *value as _;
200                    Ok(())
201                }
202                Intermediate::U16(value) => {
203                    *data = *value;
204                    Ok(())
205                }
206                _ => Err("Expected u16 value".into()),
207            },
208        );
209        self.register::<u32>(
210            |data, _, _| Ok((*data).into()),
211            |data, value, _, _, _| match value {
212                Intermediate::U8(value) => {
213                    *data = *value as _;
214                    Ok(())
215                }
216                Intermediate::U16(value) => {
217                    *data = *value as _;
218                    Ok(())
219                }
220                Intermediate::U32(value) => {
221                    *data = *value;
222                    Ok(())
223                }
224                _ => Err("Expected u32 value".into()),
225            },
226        );
227        self.register::<u64>(
228            |data, _, _| Ok((*data).into()),
229            |data, value, _, _, _| match value {
230                Intermediate::U8(value) => {
231                    *data = *value as _;
232                    Ok(())
233                }
234                Intermediate::U16(value) => {
235                    *data = *value as _;
236                    Ok(())
237                }
238                Intermediate::U32(value) => {
239                    *data = *value as _;
240                    Ok(())
241                }
242                Intermediate::U64(value) => {
243                    *data = *value;
244                    Ok(())
245                }
246                _ => Err("Expected u64 value".into()),
247            },
248        );
249        self.register::<u128>(
250            |data, _, _| Ok((*data).into()),
251            |data, value, _, _, _| match value {
252                Intermediate::U8(value) => {
253                    *data = *value as _;
254                    Ok(())
255                }
256                Intermediate::U16(value) => {
257                    *data = *value as _;
258                    Ok(())
259                }
260                Intermediate::U32(value) => {
261                    *data = *value as _;
262                    Ok(())
263                }
264                Intermediate::U64(value) => {
265                    *data = *value as _;
266                    Ok(())
267                }
268                Intermediate::U128(value) => {
269                    *data = *value;
270                    Ok(())
271                }
272                _ => Err("Expected u128 value".into()),
273            },
274        );
275        self.register::<usize>(
276            |data, _, _| Ok((*data).into()),
277            |data, value, _, _, _| match value {
278                Intermediate::U8(value) => {
279                    *data = *value as _;
280                    Ok(())
281                }
282                Intermediate::U16(value) => {
283                    *data = *value as _;
284                    Ok(())
285                }
286                Intermediate::U32(value) => {
287                    *data = *value as _;
288                    Ok(())
289                }
290                Intermediate::U64(value) => {
291                    *data = *value as _;
292                    Ok(())
293                }
294                _ => Err("Expected usize value".into()),
295            },
296        );
297        self.register::<f32>(
298            |data, _, _| Ok((*data).into()),
299            |data, value, _, _, _| match value {
300                Intermediate::I8(value) => {
301                    *data = *value as _;
302                    Ok(())
303                }
304                Intermediate::I16(value) => {
305                    *data = *value as _;
306                    Ok(())
307                }
308                Intermediate::I32(value) => {
309                    *data = *value as _;
310                    Ok(())
311                }
312                Intermediate::U8(value) => {
313                    *data = *value as _;
314                    Ok(())
315                }
316                Intermediate::U16(value) => {
317                    *data = *value as _;
318                    Ok(())
319                }
320                Intermediate::U32(value) => {
321                    *data = *value as _;
322                    Ok(())
323                }
324                Intermediate::F32(value) => {
325                    *data = *value;
326                    Ok(())
327                }
328                _ => Err("Expected f32 value".into()),
329            },
330        );
331        self.register::<f64>(
332            |data, _, _| Ok((*data).into()),
333            |data, value, _, _, _| match value {
334                Intermediate::I8(value) => {
335                    *data = *value as _;
336                    Ok(())
337                }
338                Intermediate::I16(value) => {
339                    *data = *value as _;
340                    Ok(())
341                }
342                Intermediate::I32(value) => {
343                    *data = *value as _;
344                    Ok(())
345                }
346                Intermediate::I64(value) => {
347                    *data = *value as _;
348                    Ok(())
349                }
350                Intermediate::U8(value) => {
351                    *data = *value as _;
352                    Ok(())
353                }
354                Intermediate::U16(value) => {
355                    *data = *value as _;
356                    Ok(())
357                }
358                Intermediate::U32(value) => {
359                    *data = *value as _;
360                    Ok(())
361                }
362                Intermediate::U64(value) => {
363                    *data = *value as _;
364                    Ok(())
365                }
366                Intermediate::F32(value) => {
367                    *data = *value as _;
368                    Ok(())
369                }
370                Intermediate::F64(value) => {
371                    *data = *value;
372                    Ok(())
373                }
374                _ => Err("Expected f64 value".into()),
375            },
376        );
377        self.register::<char>(
378            |data, _, _| Ok((*data).into()),
379            |data, value, _, _, _| match value {
380                Intermediate::Char(value) => {
381                    *data = *value;
382                    Ok(())
383                }
384                Intermediate::String(value) => {
385                    if let Some(value) = value.chars().next() {
386                        *data = value;
387                        Ok(())
388                    } else {
389                        Err("Expected char value (intermediate string is empty)".into())
390                    }
391                }
392                _ => Err("Expected char value".into()),
393            },
394        );
395        self.register::<String>(
396            |data, _, _| Ok(data.as_str().into()),
397            |data, value, _, initialized, _| {
398                if let Intermediate::String(value) = value {
399                    if initialized {
400                        *data = value.to_owned();
401                    } else {
402                        unsafe { (data as *mut String).write_unaligned(value.to_owned()) };
403                    }
404                    Ok(())
405                } else {
406                    Err("Expected string value".into())
407                }
408            },
409        );
410        self
411    }
412
413    pub fn with_erased_types(mut self) -> Self {
414        self.register::<DynamicManaged>(
415            |data, serializer, registry| unsafe {
416                let Some(type_handle) = registry.find_type(TypeQuery {
417                    type_hash: Some(*data.type_hash()),
418                    ..Default::default()
419                }) else {
420                    return Err(format!(
421                        "Type of DynamicManaged object not found. Hash: {}",
422                        data.type_hash()
423                    )
424                    .into());
425                };
426                let value = serializer
427                    .dynamic_serialize_from(*data.type_hash(), data.as_ptr_raw(), registry)
428                    .map_err(|error| {
429                        format!(
430                            "{}. Type: {}::{}",
431                            error,
432                            type_handle.module_name().unwrap_or(""),
433                            type_handle.name()
434                        )
435                    })?;
436                Ok(Intermediate::struct_type()
437                    .field("type", type_handle.name())
438                    .field(
439                        "module",
440                        Intermediate::Option(
441                            type_handle
442                                .module_name()
443                                .map(|name| Box::new(Intermediate::String(name.to_owned()))),
444                        ),
445                    )
446                    .field("value", value))
447            },
448            |data, value, serializer, initialized, registry| unsafe {
449                let Intermediate::Struct(fields) = value else {
450                    return Err("Expected struct value".into());
451                };
452                let Some(type_name) = fields
453                    .iter()
454                    .find(|(name, _)| name == "type")
455                    .and_then(|(_, value)| value.as_str())
456                else {
457                    return Err("Type field not found".into());
458                };
459                let Some(module_name) = fields
460                    .iter()
461                    .find(|(name, _)| name == "module")
462                    .map(|(_, value)| value.as_option().and_then(|value| value.as_str()))
463                else {
464                    return Err("Module field not found".into());
465                };
466                let Some(value) = fields
467                    .iter()
468                    .find(|(name, _)| name == "value")
469                    .map(|(_, value)| value)
470                else {
471                    return Err("Value field not found".into());
472                };
473                let Some(type_handle) = registry.find_type(TypeQuery {
474                    name: Some(type_name.into()),
475                    module_name: module_name.map(|name| name.into()),
476                    ..Default::default()
477                }) else {
478                    return Err(format!(
479                        "Type not found: {}::{}",
480                        module_name.unwrap_or(""),
481                        type_name
482                    )
483                    .into());
484                };
485                if initialized {
486                    DynamicManaged::finalize_raw(data as *mut DynamicManaged as *mut ());
487                }
488                (data as *mut DynamicManaged).write_unaligned(DynamicManaged::new_uninitialized(
489                    type_handle.type_hash(),
490                    *type_handle.layout(),
491                    type_handle.finalizer(),
492                ));
493                serializer.dynamic_deserialize_to(
494                    type_handle.type_hash(),
495                    data.as_mut_ptr_raw(),
496                    value,
497                    false,
498                    registry,
499                )
500            },
501        );
502        self.register::<DynamicManagedBox>(
503            |data, serializer, registry| unsafe {
504                let Some(type_hash) = data.type_hash() else {
505                    return Err("DynamicManagedBox type hash not found".into());
506                };
507                let Some(ptr) = data.as_ptr_raw() else {
508                    return Err("DynamicManagedBox pointer not found".into());
509                };
510                let Some(type_handle) = registry.find_type(TypeQuery {
511                    type_hash: Some(type_hash),
512                    ..Default::default()
513                }) else {
514                    return Err(format!(
515                        "Type of DynamicManagedBox object not found. Hash: {}",
516                        type_hash
517                    )
518                    .into());
519                };
520                let value = serializer
521                    .dynamic_serialize_from(type_hash, ptr, registry)
522                    .map_err(|error| {
523                        format!(
524                            "{}. Type: {}::{}",
525                            error,
526                            type_handle.module_name().unwrap_or(""),
527                            type_handle.name()
528                        )
529                    })?;
530                Ok(Intermediate::struct_type()
531                    .field("type", type_handle.name())
532                    .field(
533                        "module",
534                        Intermediate::Option(
535                            type_handle
536                                .module_name()
537                                .map(|name| Box::new(Intermediate::String(name.to_owned()))),
538                        ),
539                    )
540                    .field("value", value))
541            },
542            |data, value, serializer, initialized, registry| unsafe {
543                let Intermediate::Struct(fields) = value else {
544                    return Err("Expected struct value".into());
545                };
546                let Some(type_name) = fields
547                    .iter()
548                    .find(|(name, _)| name == "type")
549                    .and_then(|(_, value)| value.as_str())
550                else {
551                    return Err("Type field not found".into());
552                };
553                let Some(module_name) = fields
554                    .iter()
555                    .find(|(name, _)| name == "module")
556                    .map(|(_, value)| value.as_option().and_then(|value| value.as_str()))
557                else {
558                    return Err("Module field not found".into());
559                };
560                let Some(value) = fields
561                    .iter()
562                    .find(|(name, _)| name == "value")
563                    .map(|(_, value)| value)
564                else {
565                    return Err("Value field not found".into());
566                };
567                let Some(type_handle) = registry.find_type(TypeQuery {
568                    name: Some(type_name.into()),
569                    module_name: module_name.map(|name| name.into()),
570                    ..Default::default()
571                }) else {
572                    return Err(format!(
573                        "Type not found: {}::{}",
574                        module_name.unwrap_or(""),
575                        type_name
576                    )
577                    .into());
578                };
579                if initialized {
580                    DynamicManagedBox::finalize_raw(data as *mut DynamicManagedBox as *mut ());
581                }
582                (data as *mut DynamicManagedBox).write_unaligned(
583                    DynamicManagedBox::new_uninitialized(
584                        type_handle.type_hash(),
585                        *type_handle.layout(),
586                        type_handle.finalizer(),
587                    ),
588                );
589                serializer.dynamic_deserialize_to(
590                    type_handle.type_hash(),
591                    data.as_mut_ptr_raw().unwrap(),
592                    value,
593                    false,
594                    registry,
595                )
596            },
597        );
598        self.register::<CoreObject>(
599            |data, serializer, registry| unsafe {
600                let Some(type_handle) = registry.find_type(TypeQuery {
601                    type_hash: Some(data.type_handle().type_hash()),
602                    ..Default::default()
603                }) else {
604                    return Err(format!(
605                        "Type of Object not found. Hash: {}",
606                        data.type_handle().type_hash()
607                    )
608                    .into());
609                };
610                let value = serializer
611                    .dynamic_serialize_from(data.type_handle().type_hash(), data.as_ptr(), registry)
612                    .map_err(|error| {
613                        format!(
614                            "{}. Type: {}::{}",
615                            error,
616                            type_handle.module_name().unwrap_or(""),
617                            type_handle.name()
618                        )
619                    })?;
620                Ok(Intermediate::struct_type()
621                    .field("type", type_handle.name())
622                    .field(
623                        "module",
624                        Intermediate::Option(
625                            type_handle
626                                .module_name()
627                                .map(|name| Box::new(Intermediate::String(name.to_owned()))),
628                        ),
629                    )
630                    .field("value", value))
631            },
632            |data, value, serializer, initialized, registry| unsafe {
633                let Intermediate::Struct(fields) = value else {
634                    return Err("Expected struct value".into());
635                };
636                let Some(type_name) = fields
637                    .iter()
638                    .find(|(name, _)| name == "type")
639                    .and_then(|(_, value)| value.as_str())
640                else {
641                    return Err("Type field not found".into());
642                };
643                let Some(module_name) = fields
644                    .iter()
645                    .find(|(name, _)| name == "module")
646                    .map(|(_, value)| value.as_option().and_then(|value| value.as_str()))
647                else {
648                    return Err("Module field not found".into());
649                };
650                let Some(value) = fields
651                    .iter()
652                    .find(|(name, _)| name == "value")
653                    .map(|(_, value)| value)
654                else {
655                    return Err("Value field not found".into());
656                };
657                let Some(type_handle) = registry.find_type(TypeQuery {
658                    name: Some(type_name.into()),
659                    module_name: module_name.map(|name| name.into()),
660                    ..Default::default()
661                }) else {
662                    return Err(format!(
663                        "Type not found: {}::{}",
664                        module_name.unwrap_or(""),
665                        type_name
666                    )
667                    .into());
668                };
669                if initialized {
670                    CoreObject::finalize_raw(data as *mut CoreObject as *mut ());
671                }
672                (data as *mut CoreObject)
673                    .write_unaligned(CoreObject::new_uninitialized(type_handle.clone()).unwrap());
674                serializer.dynamic_deserialize_to(
675                    type_handle.type_hash(),
676                    data.as_mut_ptr(),
677                    value,
678                    false,
679                    registry,
680                )
681            },
682        );
683        self
684    }
685
686    pub fn with_serde<T: Serialize + DeserializeOwned>(mut self) -> Self {
687        self.register_serde::<T>();
688        self
689    }
690
691    pub fn with_reflection(mut self, handle: TypeHandle) -> Self {
692        self.register_reflection(handle);
693        self
694    }
695
696    pub fn with<T>(
697        mut self,
698        serialize_from: impl Fn(&T, &Self, &Registry) -> Result<Intermediate, Box<dyn Error>>
699        + Send
700        + Sync
701        + 'static,
702        deserialize_to: impl Fn(
703            &mut T,
704            &Intermediate,
705            &Self,
706            bool,
707            &Registry,
708        ) -> Result<(), Box<dyn Error>>
709        + Send
710        + Sync
711        + 'static,
712    ) -> Self {
713        self.register(serialize_from, deserialize_to);
714        self
715    }
716
717    pub fn with_raw(
718        mut self,
719        type_hash: TypeHash,
720        serialize_from: impl Fn(*const u8, &Self, &Registry) -> Result<Intermediate, Box<dyn Error>>
721        + Send
722        + Sync
723        + 'static,
724        deserialize_to: impl Fn(
725            *mut u8,
726            &Intermediate,
727            &Self,
728            bool,
729            &Registry,
730        ) -> Result<(), Box<dyn Error>>
731        + Send
732        + Sync
733        + 'static,
734    ) -> Self {
735        unsafe { self.register_raw(type_hash, serialize_from, deserialize_to) }
736        self
737    }
738
739    pub fn register_serde<T: Serialize + DeserializeOwned>(&mut self) {
740        self.register::<T>(
741            |data, _, _| Ok(serde_intermediate::to_intermediate(data)?),
742            |data, value, _, initialized, _| {
743                if initialized {
744                    *data = serde_intermediate::from_intermediate(value)?;
745                } else {
746                    unsafe {
747                        (data as *mut T)
748                            .write_unaligned(serde_intermediate::from_intermediate(value)?)
749                    };
750                }
751                Ok(())
752            },
753        );
754    }
755
756    pub fn register_reflection(&mut self, handle: TypeHandle) {
757        let handle_ser = handle.clone();
758        let handle_de = handle.clone();
759        unsafe {
760            self.register_raw(
761                handle.type_hash(),
762                move |data, serializer, registry| match &*handle_ser {
763                    Type::Struct(type_) => {
764                        let mut result = Intermediate::struct_type();
765                        for field in type_.fields() {
766                            let value = serializer.dynamic_serialize_from(
767                                field.type_handle().type_hash(),
768                                data.add(field.address_offset()),
769                                registry,
770                            )?;
771                            result = result.field(field.name.as_str(), value);
772                        }
773                        Ok(result)
774                    }
775                    Type::Enum(type_) => {
776                        let discriminant = data.read();
777                        if let Some(variant) = type_.find_variant_by_discriminant(discriminant) {
778                            let mut result = Intermediate::struct_variant(variant.name.as_str());
779                            for field in &variant.fields {
780                                let value = serializer.dynamic_serialize_from(
781                                    field.type_handle().type_hash(),
782                                    data.add(field.address_offset()),
783                                    registry,
784                                )?;
785                                result = result.field(field.name.as_str(), value);
786                            }
787                            Ok(result)
788                        } else {
789                            Err(format!(
790                                "Enum variant with discriminant: {} not found",
791                                discriminant
792                            )
793                            .into())
794                        }
795                    }
796                },
797                move |data, value, serializer, initialized, registry| match &*handle_de {
798                    Type::Struct(type_) => {
799                        fn item<'a>(
800                            value: &'a Intermediate,
801                            name: &'a str,
802                        ) -> Option<&'a Intermediate> {
803                            match value {
804                                Intermediate::Struct(value) => value
805                                    .iter()
806                                    .find_map(|(n, v)| if n == name { Some(v) } else { None }),
807                                Intermediate::Map(value) => value.iter().find_map(|(key, v)| {
808                                    if key.as_str().map(|key| key == name).unwrap_or_default() {
809                                        Some(v)
810                                    } else {
811                                        None
812                                    }
813                                }),
814                                _ => None,
815                            }
816                        }
817                        for field in type_.fields() {
818                            let data = data.add(field.address_offset());
819                            if initialized {
820                                field.type_handle().finalize(data.cast());
821                            }
822                            if let Some(value) = item(value, &field.name) {
823                                serializer.dynamic_deserialize_to(
824                                    field.type_handle().type_hash(),
825                                    data,
826                                    value,
827                                    false,
828                                    registry,
829                                )?;
830                            } else if !initialized {
831                                field.type_handle().initialize(data.cast());
832                            }
833                        }
834                        Ok(())
835                    }
836                    Type::Enum(type_) => {
837                        fn discriminant_fields<'a>(
838                            type_: &'a Enum,
839                            name: &'a str,
840                        ) -> Option<(u8, &'a [StructField])> {
841                            type_
842                                .find_variant(EnumVariantQuery {
843                                    name: Some(name.into()),
844                                    ..Default::default()
845                                })
846                                .map(|variant| (variant.discriminant(), variant.fields.as_slice()))
847                        }
848                        if initialized {
849                            type_.finalize(data.cast());
850                        }
851                        match value {
852                            Intermediate::UnitVariant(name) => {
853                                if let Some((discriminant, _)) = discriminant_fields(type_, name) {
854                                    data.write_unaligned(discriminant);
855                                } else {
856                                    return Err(format!("Enum variant: {} not found", name).into());
857                                }
858                            }
859                            Intermediate::NewTypeVariant(name, value) => {
860                                if let Some((discriminant, fields)) =
861                                    discriminant_fields(type_, name)
862                                {
863                                    let field = &fields[0];
864                                    data.write_unaligned(discriminant);
865                                    serializer.dynamic_deserialize_to(
866                                        field.type_handle().type_hash(),
867                                        data.add(field.address_offset()),
868                                        value,
869                                        false,
870                                        registry,
871                                    )?;
872                                } else {
873                                    return Err(format!("Enum variant: {} not found", name).into());
874                                }
875                            }
876                            Intermediate::TupleVariant(name, values) => {
877                                if let Some((discriminant, fields)) =
878                                    discriminant_fields(type_, name)
879                                {
880                                    data.write_unaligned(discriminant);
881                                    for field in fields {
882                                        let index = field
883                                            .name
884                                            .parse::<usize>()
885                                            .map_err(|_| "Expected tuple field name")?;
886                                        if let Some(value) = values.get(index) {
887                                            serializer.dynamic_deserialize_to(
888                                                field.type_handle().type_hash(),
889                                                data.add(field.address_offset()),
890                                                value,
891                                                false,
892                                                registry,
893                                            )?;
894                                        } else if !initialized {
895                                            field.type_handle().initialize(
896                                                data.add(field.address_offset()).cast(),
897                                            );
898                                        }
899                                    }
900                                } else {
901                                    return Err(format!("Enum variant: {} not found", name).into());
902                                }
903                            }
904                            Intermediate::StructVariant(name, values) => {
905                                if let Some((discriminant, fields)) =
906                                    discriminant_fields(type_, name)
907                                {
908                                    data.write_unaligned(discriminant);
909                                    for field in fields {
910                                        if let Some((_, value)) = values
911                                            .iter()
912                                            .find(|(key, _)| key == field.name.as_str())
913                                        {
914                                            serializer.dynamic_deserialize_to(
915                                                field.type_handle().type_hash(),
916                                                data.add(field.address_offset()),
917                                                value,
918                                                false,
919                                                registry,
920                                            )?;
921                                        } else if !initialized {
922                                            field.type_handle().initialize(
923                                                data.add(field.address_offset()).cast(),
924                                            );
925                                        }
926                                    }
927                                } else {
928                                    return Err(format!("Enum variant: {} not found", name).into());
929                                }
930                            }
931                            _ => return Err("Expected enum variant".into()),
932                        }
933                        Ok(())
934                    }
935                },
936            );
937        }
938    }
939
940    pub fn register<T>(
941        &mut self,
942        serialize_from: impl Fn(&T, &Self, &Registry) -> Result<Intermediate, Box<dyn Error>>
943        + Send
944        + Sync
945        + 'static,
946        deserialize_to: impl Fn(
947            &mut T,
948            &Intermediate,
949            &Self,
950            bool,
951            &Registry,
952        ) -> Result<(), Box<dyn Error>>
953        + Send
954        + Sync
955        + 'static,
956    ) {
957        let type_hash = TypeHash::of::<T>();
958        unsafe {
959            self.register_raw(
960                type_hash,
961                move |data, serializer, registry| {
962                    serialize_from(data.cast::<T>().as_ref().unwrap(), serializer, registry)
963                },
964                move |data, value, serialzier, initialized, registry| {
965                    deserialize_to(
966                        data.cast::<T>().as_mut().unwrap(),
967                        value,
968                        serialzier,
969                        initialized,
970                        registry,
971                    )
972                },
973            );
974        }
975    }
976
977    /// # Safety
978    pub unsafe fn register_raw(
979        &mut self,
980        type_hash: TypeHash,
981        serialize_from: impl Fn(*const u8, &Self, &Registry) -> Result<Intermediate, Box<dyn Error>>
982        + Send
983        + Sync
984        + 'static,
985        deserialize_to: impl Fn(
986            *mut u8,
987            &Intermediate,
988            &Self,
989            bool,
990            &Registry,
991        ) -> Result<(), Box<dyn Error>>
992        + Send
993        + Sync
994        + 'static,
995    ) {
996        self.mapping.insert(
997            type_hash,
998            Serializer {
999                serialize_from: Box::new(serialize_from),
1000                deserialize_to: Box::new(deserialize_to),
1001            },
1002        );
1003    }
1004
1005    pub fn unregister<T>(&mut self) {
1006        self.unregister_raw(TypeHash::of::<T>());
1007    }
1008
1009    pub fn unregister_raw(&mut self, type_hash: TypeHash) {
1010        self.mapping.remove(&type_hash);
1011    }
1012
1013    pub fn serialize_from<T>(
1014        &self,
1015        data: &T,
1016        registry: &Registry,
1017    ) -> Result<Intermediate, Box<dyn Error>> {
1018        unsafe {
1019            let type_hash = TypeHash::of::<T>();
1020            self.dynamic_serialize_from(type_hash, data as *const T as *const u8, registry)
1021                .map_err(|error| format!("{}. Type: {}", error, std::any::type_name::<T>()).into())
1022        }
1023    }
1024
1025    /// # Safety
1026    pub unsafe fn dynamic_serialize_from(
1027        &self,
1028        type_hash: TypeHash,
1029        data: *const u8,
1030        registry: &Registry,
1031    ) -> Result<Intermediate, Box<dyn Error>> {
1032        if let Some(serializer) = self.mapping.get(&type_hash) {
1033            return (serializer.serialize_from)(data, self, registry);
1034        }
1035        Err("Type does not exist in serialization registry".into())
1036    }
1037
1038    pub fn deserialize_to<T: Default>(
1039        &self,
1040        value: &Intermediate,
1041        registry: &Registry,
1042    ) -> Result<T, Box<dyn Error>> {
1043        let mut result = T::default();
1044        unsafe {
1045            self.dynamic_deserialize_to(
1046                TypeHash::of::<T>(),
1047                &mut result as *mut T as *mut u8,
1048                value,
1049                true,
1050                registry,
1051            )
1052            .map_err(|error| format!("{}. Type: {}", error, std::any::type_name::<T>()))?;
1053        }
1054        Ok(result)
1055    }
1056
1057    pub fn deserialize_into<T>(
1058        &self,
1059        result: &mut T,
1060        value: &Intermediate,
1061        registry: &Registry,
1062    ) -> Result<(), Box<dyn Error>> {
1063        unsafe {
1064            self.dynamic_deserialize_to(
1065                TypeHash::of::<T>(),
1066                result as *mut T as *mut u8,
1067                value,
1068                true,
1069                registry,
1070            )
1071            .map_err(|error| format!("{}. Type: {}", error, std::any::type_name::<T>()))?;
1072        }
1073        Ok(())
1074    }
1075
1076    /// # Safety
1077    pub unsafe fn dynamic_deserialize_to(
1078        &self,
1079        type_hash: TypeHash,
1080        data: *mut u8,
1081        value: &Intermediate,
1082        data_initialized: bool,
1083        registry: &Registry,
1084    ) -> Result<(), Box<dyn Error>> {
1085        if let Some(serializer) = self.mapping.get(&type_hash) {
1086            (serializer.deserialize_to)(data, value, self, data_initialized, registry)?;
1087            return Ok(());
1088        }
1089        Err("Type not existent in serialization registry".into())
1090    }
1091}
1092
1093#[cfg(test)]
1094mod tests {
1095    use super::*;
1096    use intuicio_core::{IntuicioEnum, IntuicioStruct, registry::Registry};
1097    use intuicio_derive::{IntuicioEnum, IntuicioStruct};
1098    use serde::Deserialize;
1099
1100    #[derive(IntuicioEnum, Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
1101    #[repr(u8)]
1102    enum Skill {
1103        #[default]
1104        Brain,
1105        Muscles(bool),
1106        Magic {
1107            power: i32,
1108        },
1109    }
1110
1111    #[derive(IntuicioStruct, Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
1112    struct Person {
1113        name: String,
1114        age: usize,
1115        skill: Skill,
1116    }
1117
1118    #[derive(IntuicioStruct)]
1119    struct Wrapper {
1120        object: DynamicManaged,
1121    }
1122
1123    impl Default for Wrapper {
1124        fn default() -> Self {
1125            Self {
1126                object: DynamicManaged::new(()).unwrap(),
1127            }
1128        }
1129    }
1130
1131    #[test]
1132    fn test_serde_serialization() {
1133        let registry = Registry::default().with_basic_types();
1134        let serialization = SerializationRegistry::default()
1135            .with_basic_types()
1136            .with_serde::<Skill>()
1137            .with_serde::<Person>();
1138
1139        let data = Person {
1140            name: "Grumpy".to_owned(),
1141            age: 24,
1142            skill: Skill::Magic { power: 42 },
1143        };
1144        let serialized = serialization.serialize_from(&data, &registry).unwrap();
1145        let data2 = serialization
1146            .deserialize_to::<Person>(&serialized, &registry)
1147            .unwrap();
1148        assert_eq!(data, data2);
1149    }
1150
1151    #[test]
1152    fn test_reflection_serialization() {
1153        let mut registry = Registry::default().with_basic_types();
1154        let skill_type = registry.add_type(Skill::define_enum(&registry));
1155        let person_type = registry.add_type(Person::define_struct(&registry));
1156        let serialization = SerializationRegistry::default()
1157            .with_basic_types()
1158            .with_reflection(skill_type)
1159            .with_reflection(person_type);
1160
1161        let data = Person {
1162            name: "Grumpy".to_owned(),
1163            age: 24,
1164            skill: Skill::Magic { power: 42 },
1165        };
1166        let serialized = serialization.serialize_from(&data, &registry).unwrap();
1167        let data2 = serialization
1168            .deserialize_to::<Person>(&serialized, &registry)
1169            .unwrap();
1170        assert_eq!(data, data2);
1171    }
1172
1173    #[test]
1174    fn test_type_erased_serialization() {
1175        let mut registry = Registry::default().with_basic_types().with_erased_types();
1176        registry.add_type(Skill::define_enum(&registry));
1177        registry.add_type(Person::define_struct(&registry));
1178        let wrapper_type = registry.add_type(Wrapper::define_struct(&registry));
1179        let serialization = SerializationRegistry::default()
1180            .with_basic_types()
1181            .with_serde::<Skill>()
1182            .with_serde::<Person>()
1183            .with_reflection(wrapper_type)
1184            .with_erased_types();
1185
1186        let data = Wrapper {
1187            object: DynamicManaged::new(Person {
1188                name: "Grumpy".to_owned(),
1189                age: 24,
1190                skill: Skill::Magic { power: 42 },
1191            })
1192            .unwrap(),
1193        };
1194        let serialized = serialization.serialize_from(&data, &registry).unwrap();
1195        let data2 = serialization
1196            .deserialize_to::<Wrapper>(&serialized, &registry)
1197            .unwrap();
1198        let data = data.object.consume::<Person>().ok().unwrap();
1199        let data2 = data2.object.consume::<Person>().ok().unwrap();
1200        assert_eq!(data, data2);
1201    }
1202}