datex_core/serde/
deserializer.rs

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