datex_core/serde/
deserializer.rs

1use crate::values::core_values::map::{Map, OwnedMapKey};
2use crate::values::value::Value;
3use crate::{
4    compiler::{
5        CompileOptions, compile_script, extract_static_value_from_script,
6    },
7    runtime::execution::{ExecutionInput, ExecutionOptions, execute_dxb_sync},
8    serde::error::DeserializationError,
9    values::{
10        core_value::CoreValue,
11        core_values::{
12            decimal::typed_decimal::TypedDecimal,
13            integer::typed_integer::TypedInteger,
14        },
15        value,
16        value_container::ValueContainer,
17    },
18};
19use serde::de::{EnumAccess, VariantAccess, Visitor};
20use serde::{Deserializer, de::IntoDeserializer, forward_to_deserialize_any};
21use std::path::PathBuf;
22
23/// Deserialize a value of type T from a byte slice containing DXB data
24pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result<T, DeserializationError>
25where
26    T: serde::Deserialize<'de>,
27{
28    let deserializer = DatexDeserializer::from_bytes(input)?;
29    T::deserialize(deserializer)
30}
31
32/// Deserialize a value of type T from a ValueContainer
33pub fn from_value_container<'de, T>(
34    value: ValueContainer,
35) -> Result<T, DeserializationError>
36where
37    T: serde::Deserialize<'de>,
38{
39    let deserializer = DatexDeserializer::from_value(value);
40    T::deserialize(deserializer)
41}
42
43#[derive(Clone)]
44pub struct DatexDeserializer {
45    pub value: ValueContainer,
46}
47
48impl<'de> DatexDeserializer {
49    /// Create a deserializer from a byte slice containing DXB data
50    /// This will execute the DXB and extract the resulting value for deserialization
51    pub fn from_bytes(input: &'de [u8]) -> Result<Self, DeserializationError> {
52        let context = ExecutionInput::new_with_dxb_and_options(
53            input,
54            ExecutionOptions { verbose: true },
55        );
56        let value = execute_dxb_sync(context)
57            .map_err(DeserializationError::ExecutionError)?
58            .expect("DXB execution returned no value");
59        Ok(Self { value })
60    }
61
62    /// Create a deserializer from a DX file path
63    /// This will read the file, compile it to DXB, execute it and extract the
64    pub fn from_dx_file(path: PathBuf) -> Result<Self, DeserializationError> {
65        let input = std::fs::read_to_string(path).map_err(|err| {
66            DeserializationError::CanNotReadFile(err.to_string())
67        })?;
68        DatexDeserializer::from_script(&input)
69    }
70
71    /// Create a deserializer from a DXB file path
72    /// This will read the file, execute it and extract the resulting value for deserialization
73    pub fn from_dxb_file(path: PathBuf) -> Result<Self, DeserializationError> {
74        let input = std::fs::read(path).map_err(|err| {
75            DeserializationError::CanNotReadFile(err.to_string())
76        })?;
77        DatexDeserializer::from_bytes(&input)
78    }
79
80    /// Create a deserializer from a DX script string
81    /// This will compile the script to DXB, execute it and extract the resulting value for deserialization
82    pub fn from_script(script: &'de str) -> Result<Self, DeserializationError> {
83        let (dxb, _) = compile_script(script, CompileOptions::default())
84            .map_err(|err| {
85                DeserializationError::CanNotReadFile(err.to_string())
86            })?;
87        DatexDeserializer::from_bytes(&dxb)
88    }
89
90    /// Create a deserializer from a DX script string
91    /// This will extract a static value from the script without executing it
92    /// and use that value for deserialization
93    /// If no static value is found, an error is returned
94    /// This is useful for deserializing simple values like integer, text, map and list
95    /// without the need to execute the script
96    /// Note: This does not support expressions or computations in the script
97    /// For example, the script `{ "key": 42 }` will work, but the script `{ "key": 40 + 2 }` will not
98    /// because the latter requires execution to evaluate the expression
99    /// and extract the value
100    pub fn from_static_script(
101        script: &'de str,
102    ) -> Result<Self, DeserializationError> {
103        let value = extract_static_value_from_script(script)
104            .map_err(DeserializationError::CompilerError)?;
105        if value.is_none() {
106            return Err(DeserializationError::NoStaticValueFound);
107        }
108        Ok(DatexDeserializer::from_value(value.unwrap()))
109    }
110
111    fn from_value(value: ValueContainer) -> Self {
112        Self { value }
113    }
114}
115
116impl<'de> IntoDeserializer<'de, DeserializationError> for DatexDeserializer {
117    type Deserializer = Self;
118
119    fn into_deserializer(self) -> Self::Deserializer {
120        self
121    }
122}
123impl<'de> Deserializer<'de> for DatexDeserializer {
124    type Error = DeserializationError;
125
126    forward_to_deserialize_any! {
127        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf
128        tuple seq unit struct ignored_any
129    }
130
131    /// Deserialize any value from the value container
132    /// This is the main entry point for deserialization
133    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
134    where
135        V: serde::de::Visitor<'de>,
136    {
137        match self.value {
138            // TODO #148 implement missing mapping
139            ValueContainer::Value(value::Value { inner, .. }) => match inner {
140                CoreValue::Null => visitor.visit_none(),
141                CoreValue::Boolean(b) => visitor.visit_bool(b.0),
142                CoreValue::TypedInteger(i) => match i {
143                    TypedInteger::I128(i) => visitor.visit_i128(i),
144                    TypedInteger::U128(u) => visitor.visit_u128(u),
145                    TypedInteger::I64(i) => visitor.visit_i64(i),
146                    TypedInteger::U64(u) => visitor.visit_u64(u),
147                    TypedInteger::I32(i) => visitor.visit_i32(i),
148                    TypedInteger::U32(u) => visitor.visit_u32(u),
149                    TypedInteger::I16(i) => visitor.visit_i16(i),
150                    TypedInteger::U16(u) => visitor.visit_u16(u),
151                    TypedInteger::I8(i) => visitor.visit_i8(i),
152                    TypedInteger::U8(u) => visitor.visit_u8(u),
153                    TypedInteger::Big(i) => {
154                        visitor.visit_i128(i.as_i128().unwrap())
155                    }
156                    e => todo!("#393 Unsupported typed integer: {:?}", e),
157                },
158                CoreValue::Integer(i) => {
159                    if let Some(v) = i.as_i8() {
160                        visitor.visit_i8(v)
161                    } else if let Some(v) = i.as_i16() {
162                        visitor.visit_i16(v)
163                    } else if let Some(v) = i.as_i32() {
164                        visitor.visit_i32(v)
165                    } else if let Some(v) = i.as_i64() {
166                        visitor.visit_i64(v)
167                    } else {
168                        visitor.visit_i128(i.as_i128().unwrap())
169                    }
170                }
171                CoreValue::Decimal(d) => todo!("#394 Unsupported decimal: {:?}", d),
172                CoreValue::TypedDecimal(d) => match d {
173                    TypedDecimal::F32(v) => visitor.visit_f32(v.0),
174                    TypedDecimal::F64(v) => visitor.visit_f64(v.0),
175                    TypedDecimal::Decimal(v) => {
176                        visitor.visit_str(&v.to_string())
177                    }
178                },
179                CoreValue::Text(s) => visitor.visit_string(s.0),
180                CoreValue::Endpoint(endpoint) => {
181                    let endpoint_str = endpoint.to_string();
182                    visitor.visit_string(endpoint_str)
183                }
184                CoreValue::Map(obj) => {
185                    let map = obj.into_iter().map(|(k, v)| {
186                        (
187                            DatexDeserializer::from_value(
188                                ValueContainer::from(k),
189                            ),
190                            DatexDeserializer::from_value(v),
191                        )
192                    });
193                    visitor
194                        .visit_map(serde::de::value::MapDeserializer::new(map))
195                }
196                CoreValue::List(list) => {
197                    let vec =
198                        list.into_iter().map(DatexDeserializer::from_value);
199                    visitor
200                        .visit_seq(serde::de::value::SeqDeserializer::new(vec))
201                }
202                e => unreachable!("Unsupported core value: {:?}", e),
203            },
204            _ => unreachable!("Refs are not supported in deserialization"),
205        }
206    }
207
208    /// Deserialize unit structs from the value container
209    /// For example:
210    ///     struct MyUnitStruct;
211    /// will be deserialized from:
212    ///     ()
213    fn deserialize_unit_struct<V>(
214        self,
215        name: &'static str,
216        visitor: V,
217    ) -> Result<V::Value, Self::Error>
218    where
219        V: Visitor<'de>,
220    {
221        visitor.visit_unit()
222    }
223
224    /// Deserialize options from null or some value in the value container
225    /// For example:
226    ///     Some(42) will be deserialized from 42
227    ///     None will be deserialized from null
228    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
229    where
230        V: serde::de::Visitor<'de>,
231    {
232        if self.value.to_value().borrow().is_null() {
233            visitor.visit_none()
234        } else {
235            visitor.visit_some(self)
236        }
237    }
238
239    /// Deserialize newtype structs from single values or tuples in the value container
240    /// For example:
241    ///     struct MyNewtypeStruct(i32);
242    /// will be deserialized from:
243    ///     42
244    /// or
245    ///     (42,)
246    fn deserialize_newtype_struct<V>(
247        self,
248        name: &'static str,
249        visitor: V,
250    ) -> Result<V::Value, Self::Error>
251    where
252        V: Visitor<'de>,
253    {
254        // TODO #395: handle structurally typed maps and lists
255        // if let ValueContainer::Value(Value {
256        //     inner: CoreValue::Array(array),
257        //     ..
258        // }) = self.value
259        // {
260        //     let values = array.into_iter().map(DatexDeserializer::from_value);
261        //     visitor.visit_seq(serde::de::value::SeqDeserializer::new(values))
262        // } else if let ValueContainer::Value(Value {
263        //     inner: CoreValue::Struct(structure),
264        //     ..
265        // }) = &self.value
266        // {
267        //     if structure.size() == 2 {
268        //         let first_entry = structure.at_unchecked(0);
269        //         if let ValueContainer::Value(Value {
270        //             inner: CoreValue::Text(text),
271        //             ..
272        //         }) = first_entry
273        //             && text.0.starts_with("datex::")
274        //         {
275        //             let second_entry = structure.at_unchecked(1);
276        //             return visitor.visit_newtype_struct(
277        //                 DatexDeserializer::from_value(second_entry.clone()),
278        //             );
279        //         }
280        //     }
281        //     visitor
282        //         .visit_newtype_struct(DatexDeserializer::from_value(self.value))
283        // } else {
284        //
285        // }
286
287        visitor.visit_seq(serde::de::value::SeqDeserializer::new(
288            vec![self.value.clone()]
289                .into_iter()
290                .map(DatexDeserializer::from_value),
291        ))
292    }
293
294    /// Deserialize tuple structs from a list in the value container
295    /// For example:
296    ///     struct MyTupleStruct(i32, String);
297    /// will be deserialized from:
298    ///     [42, "Hello"]
299    fn deserialize_tuple_struct<V>(
300        self,
301        name: &'static str,
302        len: usize,
303        visitor: V,
304    ) -> Result<V::Value, Self::Error>
305    where
306        V: Visitor<'de>,
307    {
308        if let ValueContainer::Value(Value {
309            inner: CoreValue::List(list),
310            ..
311        }) = self.value
312        {
313            visitor.visit_seq(serde::de::value::SeqDeserializer::new(
314                list.into_iter().map(DatexDeserializer::from_value),
315            ))
316        } else {
317            Err(DeserializationError::Custom(
318                "expected map for tuple struct".to_string(),
319            ))
320        }
321    }
322
323    /// Deserialize maps from list of key-value pairs
324    /// For example:
325    ///     {"key1": value1, "key2": value2}
326    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
327    where
328        V: Visitor<'de>,
329    {
330        if let ValueContainer::Value(Value {
331            inner: CoreValue::Map(map),
332            ..
333        }) = self.value
334        {
335            let entries = map.into_iter().map(|(k, v)| {
336                (
337                    DatexDeserializer::from_value(ValueContainer::from(k)),
338                    DatexDeserializer::from_value(v),
339                )
340            });
341            visitor.visit_map(serde::de::value::MapDeserializer::new(entries))
342        } else {
343            Err(DeserializationError::Custom("expected map".to_string()))
344        }
345    }
346
347    /// Deserialize identifiers from various formats:
348    /// - Direct text: "identifier"
349    /// - Single-key map: {"Identifier": ...}
350    /// - Tuple with single text element: ("identifier", ...)
351    fn deserialize_identifier<V>(
352        self,
353        visitor: V,
354    ) -> Result<V::Value, Self::Error>
355    where
356        V: Visitor<'de>,
357    {
358        match self.value {
359            // Direct text
360            ValueContainer::Value(Value {
361                inner: CoreValue::Text(s),
362                ..
363            }) => visitor.visit_string(s.0),
364
365            // Single-key map {"Identifier": ...}
366            ValueContainer::Value(Value {
367                inner: CoreValue::Map(o),
368                ..
369            }) => {
370                if o.size() == 1 {
371                    let (key, _) = o.into_iter().next().unwrap();
372                    if let OwnedMapKey::Text(string) = key {
373                        visitor.visit_string(string)
374                    } else {
375                        Err(DeserializationError::Custom(
376                            "Expected text key for identifier".to_string(),
377                        ))
378                    }
379                } else {
380                    Err(DeserializationError::Custom(
381                        "Expected single-key map for identifier".to_string(),
382                    ))
383                }
384            }
385
386            _ => Err(DeserializationError::Custom(
387                "Expected identifier".to_string(),
388            )),
389        }
390    }
391
392    /// Deserialize enums from various formats:
393    /// - Unit variants: "Variant"
394    /// - Newtype variants: {"Variant": value}
395    fn deserialize_enum<V>(
396        self,
397        _name: &str,
398        _variants: &'static [&'static str],
399        visitor: V,
400    ) -> Result<V::Value, Self::Error>
401    where
402        V: Visitor<'de>,
403    {
404        match self.value {
405            // Default representation: ("Variant", value)
406            ValueContainer::Value(Value {
407                inner: CoreValue::List(t),
408                ..
409            }) => {
410                if t.is_empty() {
411                    return Err(DeserializationError::Custom(
412                        "Expected non-empty tuple for enum".to_string(),
413                    ));
414                }
415                let deserializer = DatexDeserializer::from_value(t.into());
416                visitor.visit_enum(EnumDeserializer {
417                    variant: "_tuple".to_string(),
418                    value: deserializer,
419                })
420            }
421
422            // Map with single key = variant name
423            ValueContainer::Value(Value {
424                inner: CoreValue::Map(o),
425                ..
426            }) => {
427                if o.size() != 1 {
428                    return Err(DeserializationError::Custom(
429                        "Expected single-key map for enum".to_string(),
430                    ));
431                }
432
433                let (variant_name, value) = o.into_iter().next().unwrap();
434                if let OwnedMapKey::Text(variant) = variant_name {
435                    let deserializer = DatexDeserializer::from_value(value);
436                    visitor.visit_enum(EnumDeserializer {
437                        variant,
438                        value: deserializer,
439                    })
440                } else {
441                    Err(DeserializationError::Custom(
442                        "Expected text variant name".to_string(),
443                    ))
444                }
445            }
446            // TODO #396: handle structurally typed maps
447            // ValueContainer::Value(Value {
448            //     inner: CoreValue::Struct(o),
449            //     ..
450            // }) => {
451            //     if o.size() != 1 {
452            //         return Err(DeserializationError::Custom(
453            //             "Expected single-key object for enum".to_string(),
454            //         ));
455            //     }
456            //
457            //     let (variant_name, value) = o.into_iter().next().unwrap();
458            //
459            //     let deserializer = DatexDeserializer::from_value(value);
460            //     visitor.visit_enum(EnumDeserializer {
461            //         variant: variant_name,
462            //         value: deserializer,
463            //     })
464            // }
465
466            // unit variants stored directly as text
467            ValueContainer::Value(Value {
468                inner: CoreValue::Text(s),
469                ..
470            }) => visitor.visit_enum(EnumDeserializer {
471                variant: s.0,
472                value: DatexDeserializer::from_value(Map::default().into()),
473            }),
474
475            e => Err(DeserializationError::Custom(format!(
476                "Expected enum representation, found: {}",
477                e
478            ))),
479        }
480    }
481
482    fn is_human_readable(&self) -> bool {
483        false
484    }
485}
486
487/// Enum deserializer helper
488/// Used to deserialize enum variants
489/// For example:
490///     enum MyEnum {
491///         Variant1,
492///         Variant2(i32),
493///     }
494/// will be deserialized from:
495///     "Variant1" or {"Variant2": 42}
496struct EnumDeserializer {
497    variant: String,
498    value: DatexDeserializer,
499}
500impl<'de> EnumAccess<'de> for EnumDeserializer {
501    type Error = DeserializationError;
502    type Variant = VariantDeserializer;
503
504    fn variant_seed<V>(
505        self,
506        seed: V,
507    ) -> Result<(V::Value, Self::Variant), Self::Error>
508    where
509        V: serde::de::DeserializeSeed<'de>,
510    {
511        let variant = seed.deserialize(DatexDeserializer::from_value(
512            ValueContainer::from(self.variant),
513        ))?;
514        Ok((variant, VariantDeserializer { value: self.value }))
515    }
516}
517
518/// Variant deserializer helper
519/// Used to deserialize enum variant contents
520/// For example:
521///     enum MyEnum {
522///         Variant1,
523///         Variant2(i32),
524///     }
525/// will be deserialized from:
526///     "Variant1" or {"Variant2": 42}
527struct VariantDeserializer {
528    value: DatexDeserializer,
529}
530
531impl<'de> VariantAccess<'de> for VariantDeserializer {
532    type Error = DeserializationError;
533
534    fn unit_variant(self) -> Result<(), Self::Error> {
535        Ok(())
536    }
537
538    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
539    where
540        T: serde::de::DeserializeSeed<'de>,
541    {
542        seed.deserialize(self.value)
543    }
544
545    fn tuple_variant<V>(
546        self,
547        len: usize,
548        visitor: V,
549    ) -> Result<V::Value, Self::Error>
550    where
551        V: serde::de::Visitor<'de>,
552    {
553        self.value.deserialize_tuple(len, visitor)
554    }
555
556    fn struct_variant<V>(
557        self,
558        fields: &'static [&'static str],
559        visitor: V,
560    ) -> Result<V::Value, Self::Error>
561    where
562        V: serde::de::Visitor<'de>,
563    {
564        self.value.deserialize_struct("", fields, visitor)
565    }
566}
567
568#[cfg(test)]
569mod tests {
570    use super::*;
571    use crate::serde::serializer::to_bytes;
572    use crate::{logger::init_logger, values::core_values::endpoint::Endpoint};
573    use serde::{Deserialize, Serialize};
574
575    #[derive(Deserialize, Serialize, Debug, PartialEq)]
576    struct TestStruct {
577        field1: String,
578        field2: i32,
579    }
580
581    #[derive(Deserialize, Serialize, Debug)]
582    enum TestEnum {
583        Variant1,
584        Variant2,
585    }
586
587    #[derive(Deserialize, Serialize, Debug)]
588    struct TestStruct2 {
589        test_enum: TestEnum,
590    }
591
592    #[derive(Deserialize, Serialize, Debug)]
593    struct TestWithOptionalField {
594        optional_field: Option<String>,
595    }
596
597    #[derive(Deserialize)]
598    struct TestStructWithEndpoint {
599        endpoint: Endpoint,
600    }
601
602    #[derive(Deserialize)]
603    struct TestStructWithOptionalEndpoint {
604        endpoint: Option<Endpoint>,
605    }
606
607    #[derive(Deserialize, Serialize, Debug, PartialEq)]
608    struct TestNestedStruct {
609        nested: TestStruct,
610    }
611
612    #[test]
613    fn nested_struct_serde() {
614        let script = r#"
615            {
616                nested: {
617                    field1: "Hello",
618                    field2: 47
619                }
620            }
621        "#;
622        let deserializer = DatexDeserializer::from_script(script).unwrap();
623        let result: TestNestedStruct =
624            Deserialize::deserialize(deserializer).unwrap();
625        assert_eq!(
626            result,
627            TestNestedStruct {
628                nested: TestStruct {
629                    field1: "Hello".to_string(),
630                    field2: 47
631                }
632            }
633        );
634    }
635
636    #[test]
637    fn struct_from_bytes() {
638        let data = to_bytes(&TestStruct {
639            field1: "Hello".to_string(),
640            field2: 42,
641        })
642        .unwrap();
643        let result: TestStruct = from_bytes(&data).unwrap();
644        assert!(!result.field1.is_empty());
645    }
646
647    #[test]
648    fn from_script() {
649        init_logger();
650        let script = r#"
651            {
652                field1: "Hello",
653                field2: 42 + 5 // This will be evaluated to 47
654            }
655        "#;
656        let deserializer = DatexDeserializer::from_script(script).unwrap();
657        let result: TestStruct =
658            Deserialize::deserialize(deserializer).unwrap();
659        assert!(!result.field1.is_empty());
660    }
661
662    #[test]
663    fn test_from_static_script() {
664        let script = r#"
665            {
666                field1: "Hello",
667                field2: 42
668            }
669        "#;
670        let deserializer =
671            DatexDeserializer::from_static_script(script).unwrap();
672        let result: TestStruct =
673            Deserialize::deserialize(deserializer).unwrap();
674        assert!(!result.field1.is_empty());
675    }
676
677    #[test]
678    fn enum_1() {
679        let script = r#""Variant1""#;
680        let dxb = compile_script(script, CompileOptions::default())
681            .expect("Failed to compile script")
682            .0;
683        let deserializer = DatexDeserializer::from_bytes(&dxb)
684            .expect("Failed to create deserializer from DXB");
685        let result: TestEnum = Deserialize::deserialize(deserializer)
686            .expect("Failed to deserialize TestEnum");
687        assert!(matches!(result, TestEnum::Variant1));
688    }
689
690    #[test]
691    fn enum_2() {
692        let script = r#""Variant2""#;
693        let dxb = compile_script(script, CompileOptions::default())
694            .expect("Failed to compile script")
695            .0;
696        let deserializer = DatexDeserializer::from_bytes(&dxb)
697            .expect("Failed to create deserializer from DXB");
698        let result: TestEnum = Deserialize::deserialize(deserializer)
699            .expect("Failed to deserialize TestEnum");
700        assert!(matches!(result, TestEnum::Variant2));
701    }
702
703    #[test]
704    fn struct_with_enum() {
705        let script = r#"
706            {
707                test_enum: "Variant1"
708            }
709        "#;
710        let dxb = compile_script(script, CompileOptions::default())
711            .expect("Failed to compile script")
712            .0;
713        let deserializer = DatexDeserializer::from_bytes(&dxb)
714            .expect("Failed to create deserializer from DXB");
715        let result: TestStruct2 = Deserialize::deserialize(deserializer)
716            .expect("Failed to deserialize TestStruct2");
717        assert!(matches!(result.test_enum, TestEnum::Variant1));
718    }
719
720    #[test]
721    fn endpoint() {
722        let script = r#"
723            {
724                endpoint: @jonas
725            }
726        "#;
727        let dxb = compile_script(script, CompileOptions::default())
728            .expect("Failed to compile script")
729            .0;
730        let deserializer = DatexDeserializer::from_bytes(&dxb)
731            .expect("Failed to create deserializer from DXB");
732        let result: TestStructWithEndpoint =
733            Deserialize::deserialize(deserializer)
734                .expect("Failed to deserialize TestStructWithEndpoint");
735        assert_eq!(result.endpoint.to_string(), "@jonas");
736    }
737
738    #[test]
739    fn optional_field() {
740        let script = r#"
741            {
742                optional_field: "Optional Value"
743            }
744        "#;
745        let dxb = compile_script(script, CompileOptions::default())
746            .expect("Failed to compile script")
747            .0;
748        let deserializer = DatexDeserializer::from_bytes(&dxb)
749            .expect("Failed to create deserializer from DXB");
750        let result: TestWithOptionalField =
751            Deserialize::deserialize(deserializer)
752                .expect("Failed to deserialize TestWithOptionalField");
753        assert!(result.optional_field.is_some());
754        assert_eq!(result.optional_field.unwrap(), "Optional Value");
755    }
756
757    #[test]
758    fn optional_field_empty() {
759        let script = r#"
760            {
761                optional_field: null
762            }
763        "#;
764        let dxb = compile_script(script, CompileOptions::default())
765            .expect("Failed to compile script")
766            .0;
767        let deserializer = DatexDeserializer::from_bytes(&dxb)
768            .expect("Failed to create deserializer from DXB");
769        let result: TestWithOptionalField =
770            Deserialize::deserialize(deserializer)
771                .expect("Failed to deserialize TestWithOptionalField");
772        assert!(result.optional_field.is_none());
773    }
774
775    #[test]
776    fn optional_endpoint() {
777        let script = r#"
778            {
779                endpoint: @jonas
780            }
781        "#;
782        let dxb = compile_script(script, CompileOptions::default())
783            .expect("Failed to compile script")
784            .0;
785        let deserializer = DatexDeserializer::from_bytes(&dxb)
786            .expect("Failed to create deserializer from DXB");
787        let result: TestStructWithOptionalEndpoint =
788            Deserialize::deserialize(deserializer)
789                .expect("Failed to deserialize TestStructWithOptionalEndpoint");
790        assert!(result.endpoint.is_some());
791        assert_eq!(result.endpoint.unwrap().to_string(), "@jonas");
792    }
793
794    #[derive(Deserialize, Serialize, Debug)]
795    enum ExampleEnum {
796        Variant1(String),
797        Variant2(i32),
798    }
799
800    #[test]
801    fn map() {
802        let script = "{Variant1: \"Hello\"}";
803        let dxb = compile_script(script, CompileOptions::default())
804            .expect("Failed to compile script")
805            .0;
806        let deserializer = DatexDeserializer::from_bytes(&dxb)
807            .expect("Failed to create deserializer from DXB");
808        let result: ExampleEnum = Deserialize::deserialize(deserializer)
809            .expect("Failed to deserialize ExampleEnum");
810        assert!(matches!(result, ExampleEnum::Variant1(_)));
811
812        let script = r#"{"Variant2": 42}"#;
813        let dxb = compile_script(script, CompileOptions::default())
814            .expect("Failed to compile script")
815            .0;
816        let deserializer = DatexDeserializer::from_bytes(&dxb)
817            .expect("Failed to create deserializer from DXB");
818        let result: ExampleEnum = Deserialize::deserialize(deserializer)
819            .expect("Failed to deserialize ExampleEnum");
820        assert!(matches!(result, ExampleEnum::Variant2(_)));
821    }
822}