Skip to main content

datex_core/serde/
deserializer.rs

1use crate::{
2    runtime::execution::{ExecutionInput, ExecutionOptions, execute_dxb_sync},
3    serde::error::DeserializationError,
4    values::{
5        core_value::CoreValue,
6        core_values::{
7            integer::typed_integer::TypedInteger, map::BorrowedMapKey,
8        },
9        value,
10        value::Value,
11        value_container::ValueContainer,
12    },
13};
14use core::{result::Result, unreachable};
15use serde::{
16    Deserialize, Deserializer,
17    de::{
18        DeserializeOwned, EnumAccess, IntoDeserializer, VariantAccess, Visitor,
19        value::StrDeserializer,
20    },
21    forward_to_deserialize_any,
22};
23
24use crate::{prelude::*, runtime::RuntimeInternal};
25
26/// Deserialize a value of type T from a byte slice containing DXB data
27pub fn from_bytes<T>(input: &[u8]) -> Result<T, DeserializationError>
28where
29    T: DeserializeOwned,
30{
31    let runtime = RuntimeInternal::stub();
32    let context = ExecutionInput::new(
33        input,
34        ExecutionOptions { verbose: true },
35        Rc::new(runtime),
36    );
37    let value = execute_dxb_sync(context)
38        .map_err(DeserializationError::ExecutionError)?
39        .expect("DXB execution returned no value");
40
41    let deserializer = DatexDeserializer::new_from_value_container(&value);
42    T::deserialize(deserializer)
43}
44
45#[cfg(feature = "compiler")]
46pub fn from_script<T>(script: &str) -> Result<T, DeserializationError>
47where
48    T: DeserializeOwned,
49{
50    let (dxb, _) = crate::compiler::compile_script(
51        script,
52        crate::compiler::CompileOptions::default(),
53    )
54    .map_err(|err| DeserializationError::CanNotReadFile(err.to_string()))?;
55    from_bytes(&dxb)
56}
57
58#[cfg(all(feature = "std", feature = "compiler"))]
59pub fn from_dx_file<T>(
60    path: std::path::PathBuf,
61) -> Result<T, DeserializationError>
62where
63    T: DeserializeOwned,
64{
65    let input = std::fs::read_to_string(path)
66        .map_err(|err| DeserializationError::CanNotReadFile(err.to_string()))?;
67    from_script(&input)
68}
69
70/// Create a deserializer from a DX script string
71/// This will extract a static value from the script without executing it
72/// and use that value for deserialization
73/// If no static value is found, an error is returned
74/// This is useful for deserializing simple values like integer, text, map and list
75/// without the need to execute the script
76/// Note: This does not support expressions or computations in the script
77/// For example, the script `{ "key": 42 }` will work, but the script `{ "key": 40 + 2 }` will not
78/// because the latter requires execution to evaluate the expression
79/// and extract the value
80#[cfg(feature = "compiler")]
81pub fn from_static_script<T>(script: &str) -> Result<T, DeserializationError>
82where
83    T: DeserializeOwned,
84{
85    let value = crate::compiler::extract_static_value_from_script(script)
86        .map_err(DeserializationError::CompilerError)?
87        .ok_or(DeserializationError::NoStaticValueFound)?;
88    let deserializer = DatexDeserializer::new_from_value_container(&value);
89    T::deserialize(deserializer)
90}
91
92/// Deserialize a value of type T from a ValueContainer
93pub fn from_value_container<T>(
94    value: &ValueContainer,
95) -> Result<T, DeserializationError>
96where
97    T: serde::de::DeserializeOwned,
98{
99    let deserializer = DatexDeserializer::new_from_value_container(value);
100    T::deserialize(deserializer)
101}
102
103#[derive(Clone)]
104pub enum DatexDeserializer<'de> {
105    ValueContainer(&'de ValueContainer),
106    Text(&'de str),
107}
108
109impl<'de> DatexDeserializer<'de> {
110    fn new_from_value_container(value: &'de ValueContainer) -> Self {
111        Self::ValueContainer(value)
112    }
113    fn new_from_str(text: &'de str) -> Self {
114        Self::Text(text)
115    }
116    fn new_from_borrowed_map_key(key: BorrowedMapKey<'de>) -> Self {
117        match key {
118            BorrowedMapKey::Text(s) => Self::Text(s),
119            BorrowedMapKey::Value(v) => Self::ValueContainer(v),
120        }
121    }
122
123    pub(crate) fn to_value_container(&self) -> Cow<'de, ValueContainer> {
124        match self {
125            DatexDeserializer::ValueContainer(v) => Cow::Borrowed(v),
126            DatexDeserializer::Text(s) => Cow::Owned(ValueContainer::from(*s)),
127        }
128    }
129}
130
131impl<'de> IntoDeserializer<'de, DeserializationError>
132    for DatexDeserializer<'de>
133{
134    type Deserializer = Self;
135
136    fn into_deserializer(self) -> Self::Deserializer {
137        self
138    }
139}
140impl<'de> Deserializer<'de> for DatexDeserializer<'de> {
141    type Error = DeserializationError;
142
143    forward_to_deserialize_any! {
144        bool char str string bytes byte_buf
145        tuple seq unit struct ignored_any
146    }
147
148    /// Deserialize any value from the value container
149    /// This is the main entry point for deserialization
150    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
151    where
152        V: serde::de::Visitor<'de>,
153    {
154        match self {
155            DatexDeserializer::Text(s) => visitor.visit_string(s.to_string()),
156            DatexDeserializer::ValueContainer(value) => match value {
157                // TODO #148 implement missing mapping
158                ValueContainer::Local(value::Value { inner, .. }) => {
159                    match inner {
160                        CoreValue::Null => visitor.visit_none(),
161                        CoreValue::Boolean(b) => visitor.visit_bool(b.0),
162                        CoreValue::TypedInteger(i) => match i {
163                            TypedInteger::I128(i) => visitor.visit_i128(*i),
164                            TypedInteger::U128(u) => visitor.visit_u128(*u),
165                            TypedInteger::I64(i) => visitor.visit_i64(*i),
166                            TypedInteger::U64(u) => visitor.visit_u64(*u),
167                            TypedInteger::I32(i) => visitor.visit_i32(*i),
168                            TypedInteger::U32(u) => visitor.visit_u32(*u),
169                            TypedInteger::I16(i) => visitor.visit_i16(*i),
170                            TypedInteger::U16(u) => visitor.visit_u16(*u),
171                            TypedInteger::I8(i) => visitor.visit_i8(*i),
172                            TypedInteger::U8(u) => visitor.visit_u8(*u),
173                            TypedInteger::IBig(i) => {
174                                visitor.visit_i128(i.as_i128().unwrap())
175                            }
176                        },
177                        CoreValue::Text(s) => visitor.visit_string(s.0.clone()),
178                        CoreValue::Endpoint(endpoint) => {
179                            let endpoint_str = endpoint.to_string();
180                            visitor.visit_string(endpoint_str)
181                        }
182                        CoreValue::Map(obj) => {
183                            let map = obj
184                                .iter()
185                                .map(|(k, v)| {
186                                    (
187                                DatexDeserializer::new_from_borrowed_map_key(k),
188                                DatexDeserializer::new_from_value_container(v),
189                            )
190                                })
191                                .collect::<Vec<_>>();
192                            visitor.visit_map(
193                                serde::de::value::MapDeserializer::new(
194                                    map.into_iter(),
195                                ),
196                            )
197                        }
198                        CoreValue::List(list) => {
199                            let vec: Vec<DatexDeserializer<'de>> = list
200                                .iter()
201                                .map(
202                                    DatexDeserializer::new_from_value_container,
203                                )
204                                .collect::<Vec<_>>();
205                            visitor.visit_seq(
206                                serde::de::value::SeqDeserializer::new(
207                                    vec.into_iter(),
208                                ),
209                            )
210                        }
211                        e => unreachable!("Unsupported core value: {:?}", e),
212                    }
213                }
214                _ => unreachable!("Refs are not supported in deserialization"),
215            },
216        }
217    }
218
219    /// Deserialize unit structs from the value container
220    /// For example:
221    ///     struct MyUnitStruct;
222    /// will be deserialized from:
223    ///     ()
224    fn deserialize_unit_struct<V>(
225        self,
226        _name: &'static str,
227        visitor: V,
228    ) -> Result<V::Value, Self::Error>
229    where
230        V: Visitor<'de>,
231    {
232        visitor.visit_unit()
233    }
234
235    /// Deserialize options from null or some value in the value container
236    /// For example:
237    ///     Some(42) will be deserialized from 42
238    ///     None will be deserialized from null
239    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
240    where
241        V: serde::de::Visitor<'de>,
242    {
243        match self {
244            DatexDeserializer::ValueContainer(value)
245                if value.to_value().borrow().is_null() =>
246            {
247                visitor.visit_none()
248            }
249            _ => visitor.visit_some(self),
250        }
251    }
252
253    /// Deserialize newtype structs from single values or tuples in the value container
254    /// For example:
255    ///     struct MyNewtypeStruct(i32);
256    /// will be deserialized from:
257    ///     42
258    /// or
259    ///     (42,)
260    fn deserialize_newtype_struct<V>(
261        self,
262        _name: &'static str,
263        visitor: V,
264    ) -> Result<V::Value, Self::Error>
265    where
266        V: Visitor<'de>,
267    {
268        // TODO #395: handle structurally typed maps and lists
269        // if let ValueContainer::Value(Value {
270        //     inner: CoreValue::Array(array),
271        //     ..
272        // }) = self.value
273        // {
274        //     let values = array.into_iter().map(DatexDeserializer::from_value);
275        //     visitor.visit_seq(serde::de::value::SeqDeserializer::new(values))
276        // } else if let ValueContainer::Value(Value {
277        //     inner: CoreValue::Struct(structure),
278        //     ..
279        // }) = &self.value
280        // {
281        //     if structure.size() == 2 {
282        //         let first_entry = structure.at_unchecked(0);
283        //         if let ValueContainer::Value(Value {
284        //             inner: CoreValue::Text(text),
285        //             ..
286        //         }) = first_entry
287        //             && text.0.starts_with("datex::")
288        //         {
289        //             let second_entry = structure.at_unchecked(1);
290        //             return visitor.visit_newtype_struct(
291        //                 DatexDeserializer::from_value(second_entry.clone()),
292        //             );
293        //         }
294        //     }
295        //     visitor
296        //         .visit_newtype_struct(DatexDeserializer::from_value(self.value))
297        // } else {
298        //
299        // }
300
301        visitor.visit_seq(serde::de::value::SeqDeserializer::new(
302            vec![self].into_iter(),
303        ))
304    }
305
306    /// Deserialize tuple structs from a list in the value container
307    /// For example:
308    ///     struct MyTupleStruct(i32, String);
309    /// will be deserialized from:
310    ///     [42, "Hello"]
311    fn deserialize_tuple_struct<V>(
312        self,
313        _name: &'static str,
314        _len: usize,
315        visitor: V,
316    ) -> Result<V::Value, Self::Error>
317    where
318        V: Visitor<'de>,
319    {
320        if let DatexDeserializer::ValueContainer(ValueContainer::Local(
321            Value {
322                inner: CoreValue::List(list),
323                ..
324            },
325        )) = self
326        {
327            visitor.visit_seq(serde::de::value::SeqDeserializer::new(
328                list.iter().map(DatexDeserializer::new_from_value_container),
329            ))
330        } else {
331            Err(DeserializationError::Custom(
332                "expected map for tuple struct".to_string(),
333            ))
334        }
335    }
336
337    /// Deserialize maps from list of key-value pairs
338    /// For example:
339    ///     {"key1": value1, "key2": value2}
340    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
341    where
342        V: Visitor<'de>,
343    {
344        if let DatexDeserializer::ValueContainer(ValueContainer::Local(
345            Value {
346                inner: CoreValue::Map(map),
347                ..
348            },
349        )) = self
350        {
351            let entries = map.iter().map(|(k, v)| {
352                (
353                    DatexDeserializer::new_from_borrowed_map_key(k),
354                    DatexDeserializer::new_from_value_container(v),
355                )
356            });
357            visitor.visit_map(serde::de::value::MapDeserializer::new(entries))
358        } else {
359            Err(DeserializationError::Custom("expected map".to_string()))
360        }
361    }
362
363    /// Deserialize identifiers from various formats:
364    /// - Direct text: "identifier"
365    /// - Single-key map: {"Identifier": ...}
366    /// - Tuple with single text element: ("identifier", ...)
367    fn deserialize_identifier<V>(
368        self,
369        visitor: V,
370    ) -> Result<V::Value, Self::Error>
371    where
372        V: Visitor<'de>,
373    {
374        match self {
375            DatexDeserializer::Text(s) => visitor.visit_string(s.to_string()),
376            DatexDeserializer::ValueContainer(value) => match value {
377                // Direct text
378                ValueContainer::Local(Value {
379                    inner: CoreValue::Text(s),
380                    ..
381                }) => visitor.visit_string(s.0.clone()),
382
383                // Single-key map {"Identifier": ...}
384                ValueContainer::Local(Value {
385                    inner: CoreValue::Map(o),
386                    ..
387                }) => {
388                    if o.size() == 1 {
389                        let (key, _) = o.iter().next().unwrap();
390                        if let BorrowedMapKey::Text(string) = key {
391                            visitor.visit_string(string.to_string())
392                        } else {
393                            Err(DeserializationError::Custom(
394                                "Expected text key for identifier".to_string(),
395                            ))
396                        }
397                    } else {
398                        Err(DeserializationError::Custom(
399                            "Expected single-key map for identifier"
400                                .to_string(),
401                        ))
402                    }
403                }
404
405                _ => Err(DeserializationError::Custom(
406                    "Expected identifier".to_string(),
407                )),
408            },
409        }
410    }
411
412    /// Deserialize enums from various formats:
413    /// - Unit variants: "Variant"
414    /// - Newtype variants: {"Variant": value}
415    fn deserialize_enum<V>(
416        self,
417        _name: &str,
418        _variants: &'static [&'static str],
419        visitor: V,
420    ) -> Result<V::Value, Self::Error>
421    where
422        V: Visitor<'de>,
423    {
424        match self {
425            DatexDeserializer::Text(s) => {
426                visitor.visit_enum(EnumDeserializer {
427                    variant: s,
428                    value: None,
429                })
430            }
431            DatexDeserializer::ValueContainer(value) => match value {
432                // Default representation: ("Variant", value)
433                value @ ValueContainer::Local(Value {
434                    inner: CoreValue::List(t),
435                    ..
436                }) => {
437                    if t.is_empty() {
438                        return Err(DeserializationError::Custom(
439                            "Expected non-empty tuple for enum".to_string(),
440                        ));
441                    }
442                    let deserializer =
443                        DatexDeserializer::new_from_value_container(value);
444                    visitor.visit_enum(EnumDeserializer {
445                        variant: "_tuple",
446                        value: Some(deserializer),
447                    })
448                }
449
450                // Map with single key = variant name
451                ValueContainer::Local(Value {
452                    inner: CoreValue::Map(o),
453                    ..
454                }) => {
455                    if o.size() != 1 {
456                        return Err(DeserializationError::Custom(
457                            "Expected single-key map for enum".to_string(),
458                        ));
459                    }
460
461                    let (variant_name, value) = o.iter().next().unwrap();
462                    if let BorrowedMapKey::Text(variant) = variant_name {
463                        let deserializer =
464                            DatexDeserializer::new_from_value_container(value);
465                        visitor.visit_enum(EnumDeserializer {
466                            variant,
467                            value: Some(deserializer),
468                        })
469                    } else {
470                        Err(DeserializationError::Custom(
471                            "Expected text variant name".to_string(),
472                        ))
473                    }
474                }
475                // TODO #396: handle structurally typed maps
476                // ValueContainer::Value(Value {
477                //     inner: CoreValue::Struct(o),
478                //     ..
479                // }) => {
480                //     if o.size() != 1 {
481                //         return Err(DeserializationError::Custom(
482                //             "Expected single-key object for enum".to_string(),
483                //         ));
484                //     }
485                //
486                //     let (variant_name, value) = o.into_iter().next().unwrap();
487                //
488                //     let deserializer = DatexDeserializer::from_value(value);
489                //     visitor.visit_enum(EnumDeserializer {
490                //         variant: variant_name,
491                //         value: deserializer,
492                //     })
493                // }
494
495                // unit variants stored directly as text
496                ValueContainer::Local(Value {
497                    inner: CoreValue::Text(s),
498                    ..
499                }) => visitor.visit_enum(EnumDeserializer {
500                    variant: &s.0,
501                    value: None,
502                }),
503
504                e => Err(DeserializationError::Custom(format!(
505                    "Expected enum representation, found: {}",
506                    e
507                ))),
508            },
509        }
510    }
511
512    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
513    where
514        V: Visitor<'de>,
515    {
516        match self {
517            DatexDeserializer::Text(_s) => {
518                Err(DeserializationError::CanNotDeserialize("f32".to_string()))
519            }
520            DatexDeserializer::ValueContainer(value) => {
521                match &value.to_value().borrow().inner {
522                    CoreValue::Decimal(decimal) => {
523                        visitor.visit_f32(decimal.into_f32())
524                    }
525                    CoreValue::TypedDecimal(typed_decimal) => {
526                        visitor.visit_f32(typed_decimal.as_f32())
527                    }
528                    CoreValue::Integer(integer) => {
529                        visitor.visit_f32(integer.as_f32())
530                    }
531                    CoreValue::TypedInteger(typed_integer) => {
532                        visitor.visit_f32(typed_integer.as_f32())
533                    }
534                    _ => Err(DeserializationError::CanNotDeserialize(
535                        "f32".to_string(),
536                    )),
537                }
538            }
539        }
540    }
541
542    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
543    where
544        V: Visitor<'de>,
545    {
546        match self {
547            DatexDeserializer::Text(_s) => {
548                Err(DeserializationError::CanNotDeserialize("f64".to_string()))
549            }
550            DatexDeserializer::ValueContainer(value) => {
551                match &value.to_value().borrow().inner {
552                    CoreValue::Decimal(decimal) => {
553                        visitor.visit_f64(decimal.into_f64())
554                    }
555                    CoreValue::TypedDecimal(typed_decimal) => {
556                        visitor.visit_f64(typed_decimal.as_f64())
557                    }
558                    CoreValue::Integer(integer) => {
559                        visitor.visit_f64(integer.as_f64())
560                    }
561                    CoreValue::TypedInteger(typed_integer) => {
562                        visitor.visit_f64(typed_integer.as_f64())
563                    }
564                    _ => Err(DeserializationError::CanNotDeserialize(
565                        "f64".to_string(),
566                    )),
567                }
568            }
569        }
570    }
571
572    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
573    where
574        V: Visitor<'de>,
575    {
576        match self {
577            DatexDeserializer::Text(_s) => {
578                Err(DeserializationError::CanNotDeserialize("i8".to_string()))
579            }
580            DatexDeserializer::ValueContainer(value) => {
581                match &value.to_value().borrow().inner {
582                    CoreValue::Integer(i) => {
583                        visitor.visit_i8(i.as_wrapped_i8())
584                    }
585                    CoreValue::TypedInteger(i) => {
586                        visitor.visit_i8(i.as_integer().as_wrapped_i8())
587                    }
588                    CoreValue::Decimal(d) => {
589                        visitor.visit_i8(d.as_integer().unwrap() as i8)
590                    }
591                    CoreValue::TypedDecimal(d) => {
592                        visitor.visit_i8(d.as_integer().unwrap() as i8)
593                    }
594                    _ => Err(DeserializationError::CanNotDeserialize(
595                        "i8".to_string(),
596                    )),
597                }
598            }
599        }
600    }
601
602    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
603    where
604        V: Visitor<'de>,
605    {
606        match self {
607            DatexDeserializer::Text(_s) => {
608                Err(DeserializationError::CanNotDeserialize("i16".to_string()))
609            }
610            DatexDeserializer::ValueContainer(value) => {
611                match &value.to_value().borrow().inner {
612                    CoreValue::Integer(i) => {
613                        visitor.visit_i16(i.as_wrapped_i16())
614                    }
615                    CoreValue::TypedInteger(i) => {
616                        visitor.visit_i16(i.as_integer().as_wrapped_i16())
617                    }
618                    CoreValue::Decimal(d) => {
619                        visitor.visit_i16(d.as_integer().unwrap() as i16)
620                    }
621                    CoreValue::TypedDecimal(d) => {
622                        visitor.visit_i16(d.as_integer().unwrap() as i16)
623                    }
624                    _ => Err(DeserializationError::CanNotDeserialize(
625                        "i16".to_string(),
626                    )),
627                }
628            }
629        }
630    }
631
632    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
633    where
634        V: Visitor<'de>,
635    {
636        match self {
637            DatexDeserializer::Text(_s) => {
638                Err(DeserializationError::CanNotDeserialize("i32".to_string()))
639            }
640            DatexDeserializer::ValueContainer(value) => {
641                match &value.to_value().borrow().inner {
642                    CoreValue::Integer(i) => {
643                        visitor.visit_i32(i.as_wrapped_i32())
644                    }
645                    CoreValue::TypedInteger(i) => {
646                        visitor.visit_i32(i.as_integer().as_wrapped_i32())
647                    }
648                    CoreValue::Decimal(d) => {
649                        visitor.visit_i32(d.as_integer().unwrap() as i32)
650                    }
651                    CoreValue::TypedDecimal(d) => {
652                        visitor.visit_i32(d.as_integer().unwrap() as i32)
653                    }
654                    _ => Err(DeserializationError::CanNotDeserialize(
655                        "i32".to_string(),
656                    )),
657                }
658            }
659        }
660    }
661
662    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
663    where
664        V: Visitor<'de>,
665    {
666        match self {
667            DatexDeserializer::Text(_s) => {
668                Err(DeserializationError::CanNotDeserialize("i64".to_string()))
669            }
670            DatexDeserializer::ValueContainer(value) => {
671                match &value.to_value().borrow().inner {
672                    CoreValue::Integer(i) => {
673                        visitor.visit_i64(i.as_wrapped_i64())
674                    }
675                    CoreValue::TypedInteger(i) => {
676                        visitor.visit_i64(i.as_integer().as_wrapped_i64())
677                    }
678                    CoreValue::Decimal(d) => {
679                        visitor.visit_i64(d.as_integer().unwrap())
680                    }
681                    CoreValue::TypedDecimal(d) => {
682                        visitor.visit_i64(d.as_integer().unwrap())
683                    }
684                    _ => Err(DeserializationError::CanNotDeserialize(
685                        "i64".to_string(),
686                    )),
687                }
688            }
689        }
690    }
691
692    fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
693    where
694        V: Visitor<'de>,
695    {
696        match self {
697            DatexDeserializer::Text(_s) => {
698                Err(DeserializationError::CanNotDeserialize("i128".to_string()))
699            }
700            DatexDeserializer::ValueContainer(value) => {
701                match &value.to_value().borrow().inner {
702                    CoreValue::Integer(i) => {
703                        visitor.visit_i128(i.as_wrapped_i128())
704                    }
705                    CoreValue::TypedInteger(i) => {
706                        visitor.visit_i128(i.as_integer().as_wrapped_i128())
707                    }
708                    CoreValue::Decimal(d) => {
709                        visitor.visit_i128(d.as_integer().unwrap() as i128)
710                    }
711                    CoreValue::TypedDecimal(d) => {
712                        visitor.visit_i128(d.as_integer().unwrap() as i128)
713                    }
714                    _ => Err(DeserializationError::CanNotDeserialize(
715                        "i128".to_string(),
716                    )),
717                }
718            }
719        }
720    }
721
722    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
723    where
724        V: Visitor<'de>,
725    {
726        match self {
727            DatexDeserializer::Text(_s) => {
728                Err(DeserializationError::CanNotDeserialize("u8".to_string()))
729            }
730            DatexDeserializer::ValueContainer(value) => {
731                match &value.to_value().borrow().inner {
732                    CoreValue::Integer(i) => {
733                        visitor.visit_u8(i.as_wrapped_u8())
734                    }
735                    CoreValue::TypedInteger(i) => {
736                        visitor.visit_u8(i.as_integer().as_wrapped_u8())
737                    }
738                    CoreValue::Decimal(d) => {
739                        visitor.visit_u8(d.as_integer().unwrap() as u8)
740                    }
741                    CoreValue::TypedDecimal(d) => {
742                        visitor.visit_u8(d.as_integer().unwrap() as u8)
743                    }
744                    _ => Err(DeserializationError::CanNotDeserialize(
745                        "u8".to_string(),
746                    )),
747                }
748            }
749        }
750    }
751
752    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
753    where
754        V: Visitor<'de>,
755    {
756        match self {
757            DatexDeserializer::Text(_s) => {
758                Err(DeserializationError::CanNotDeserialize("u16".to_string()))
759            }
760            DatexDeserializer::ValueContainer(value) => {
761                match &value.to_value().borrow().inner {
762                    CoreValue::Integer(i) => {
763                        visitor.visit_u16(i.as_wrapped_u16())
764                    }
765                    CoreValue::TypedInteger(i) => {
766                        visitor.visit_u16(i.as_integer().as_wrapped_u16())
767                    }
768                    CoreValue::Decimal(d) => {
769                        visitor.visit_u16(d.as_integer().unwrap() as u16)
770                    }
771                    CoreValue::TypedDecimal(d) => {
772                        visitor.visit_u16(d.as_integer().unwrap() as u16)
773                    }
774                    _ => Err(DeserializationError::CanNotDeserialize(
775                        "u16".to_string(),
776                    )),
777                }
778            }
779        }
780    }
781
782    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
783    where
784        V: Visitor<'de>,
785    {
786        match self {
787            DatexDeserializer::Text(_s) => {
788                Err(DeserializationError::CanNotDeserialize("u32".to_string()))
789            }
790            DatexDeserializer::ValueContainer(value) => {
791                match &value.to_value().borrow().inner {
792                    CoreValue::Integer(i) => {
793                        visitor.visit_u32(i.as_wrapped_u32())
794                    }
795                    CoreValue::TypedInteger(i) => {
796                        visitor.visit_u32(i.as_integer().as_wrapped_u32())
797                    }
798                    CoreValue::Decimal(d) => {
799                        visitor.visit_u32(d.as_integer().unwrap() as u32)
800                    }
801                    CoreValue::TypedDecimal(d) => {
802                        visitor.visit_u32(d.as_integer().unwrap() as u32)
803                    }
804                    _ => Err(DeserializationError::CanNotDeserialize(
805                        "u32".to_string(),
806                    )),
807                }
808            }
809        }
810    }
811
812    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
813    where
814        V: Visitor<'de>,
815    {
816        match self {
817            DatexDeserializer::Text(_s) => {
818                Err(DeserializationError::CanNotDeserialize("u64".to_string()))
819            }
820            DatexDeserializer::ValueContainer(value) => {
821                match &value.to_value().borrow().inner {
822                    CoreValue::Integer(i) => {
823                        visitor.visit_u64(i.as_wrapped_u64())
824                    }
825                    CoreValue::TypedInteger(i) => {
826                        visitor.visit_u64(i.as_integer().as_wrapped_u64())
827                    }
828                    CoreValue::Decimal(d) => {
829                        visitor.visit_u64(d.as_integer().unwrap() as u64)
830                    }
831                    CoreValue::TypedDecimal(d) => {
832                        visitor.visit_u64(d.as_integer().unwrap() as u64)
833                    }
834                    _ => Err(DeserializationError::CanNotDeserialize(
835                        "u64".to_string(),
836                    )),
837                }
838            }
839        }
840    }
841
842    fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value, Self::Error>
843    where
844        V: Visitor<'de>,
845    {
846        match self {
847            DatexDeserializer::Text(_s) => {
848                Err(DeserializationError::CanNotDeserialize("u128".to_string()))
849            }
850            DatexDeserializer::ValueContainer(value) => {
851                match &value.to_value().borrow().inner {
852                    CoreValue::Integer(i) => {
853                        visitor.visit_u128(i.as_wrapped_u128())
854                    }
855                    CoreValue::TypedInteger(i) => {
856                        visitor.visit_u128(i.as_integer().as_wrapped_u128())
857                    }
858                    CoreValue::Decimal(d) => {
859                        visitor.visit_u128(d.as_integer().unwrap() as u128)
860                    }
861                    CoreValue::TypedDecimal(d) => {
862                        visitor.visit_u128(d.as_integer().unwrap() as u128)
863                    }
864                    _ => Err(DeserializationError::CanNotDeserialize(
865                        "u128".to_string(),
866                    )),
867                }
868            }
869        }
870    }
871
872    fn is_human_readable(&self) -> bool {
873        false
874    }
875}
876
877/// Enum deserializer helper
878/// Used to deserialize enum variants
879/// For example:
880///     enum MyEnum {
881///         Variant1,
882///         Variant2(i32),
883///     }
884/// will be deserialized from:
885///     "Variant1" or {"Variant2": 42}
886struct EnumDeserializer<'de> {
887    variant: &'de str,
888    value: Option<DatexDeserializer<'de>>,
889}
890impl<'de> EnumAccess<'de> for EnumDeserializer<'de> {
891    type Error = DeserializationError;
892    type Variant = VariantDeserializer<'de>;
893
894    fn variant_seed<V>(
895        self,
896        seed: V,
897    ) -> Result<(V::Value, Self::Variant), Self::Error>
898    where
899        V: serde::de::DeserializeSeed<'de>,
900    {
901        let variant = seed.deserialize::<StrDeserializer<Self::Error>>(
902            self.variant.into_deserializer(),
903        )?;
904        Ok((variant, VariantDeserializer { value: self.value }))
905    }
906}
907
908/// Variant deserializer helper
909/// Used to deserialize enum variant contents
910/// For example:
911///     enum MyEnum {
912///         Variant1,
913///         Variant2(i32),
914///     }
915/// will be deserialized from:
916///     "Variant1" or {"Variant2": 42}
917struct VariantDeserializer<'de> {
918    value: Option<DatexDeserializer<'de>>,
919}
920
921impl<'de> VariantAccess<'de> for VariantDeserializer<'de> {
922    type Error = DeserializationError;
923
924    fn unit_variant(self) -> Result<(), Self::Error> {
925        Ok(())
926    }
927
928    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
929    where
930        T: serde::de::DeserializeSeed<'de>,
931    {
932        match self.value {
933            Some(value) => seed.deserialize(value),
934            None => Err(DeserializationError::Custom(
935                "Expected value for newtype variant".to_string(),
936            )),
937        }
938    }
939
940    fn tuple_variant<V>(
941        self,
942        len: usize,
943        visitor: V,
944    ) -> Result<V::Value, Self::Error>
945    where
946        V: serde::de::Visitor<'de>,
947    {
948        match self.value {
949            Some(value) => value.deserialize_tuple(len, visitor),
950            None => visitor.visit_unit(),
951        }
952    }
953
954    fn struct_variant<V>(
955        self,
956        fields: &'static [&'static str],
957        visitor: V,
958    ) -> Result<V::Value, Self::Error>
959    where
960        V: serde::de::Visitor<'de>,
961    {
962        match self.value {
963            Some(value) => value.deserialize_struct("", fields, visitor),
964            None => visitor.visit_unit(),
965        }
966    }
967}
968
969#[cfg(test)]
970#[cfg(feature = "compiler")]
971mod tests {
972    use super::*;
973    use crate::{
974        compiler::{CompileOptions, compile_script},
975        serde::serializer::to_bytes,
976        values::core_values::endpoint::Endpoint,
977    };
978    use serde::{Deserialize, Serialize};
979
980    use crate::prelude::*;
981    #[derive(Deserialize, Serialize, Debug, PartialEq)]
982    struct TestStruct {
983        field1: String,
984        field2: i32,
985    }
986
987    #[derive(Deserialize, Serialize, Debug)]
988    enum TestEnum {
989        Variant1,
990        Variant2,
991    }
992
993    #[derive(Deserialize, Serialize, Debug)]
994    struct TestStruct2 {
995        test_enum: TestEnum,
996    }
997
998    #[derive(Deserialize, Serialize, Debug)]
999    struct TestWithOptionalField {
1000        optional_field: Option<String>,
1001    }
1002
1003    #[derive(Deserialize)]
1004    struct TestStructWithEndpoint {
1005        endpoint: Endpoint,
1006    }
1007
1008    #[derive(Deserialize)]
1009    struct TestStructWithOptionalEndpoint {
1010        endpoint: Option<Endpoint>,
1011    }
1012
1013    #[derive(Deserialize, Serialize, Debug, PartialEq)]
1014    struct TestNestedStruct {
1015        nested: TestStruct,
1016    }
1017
1018    #[test]
1019    fn nested_struct_serde() {
1020        let script = r#"
1021            {
1022                nested: {
1023                    field1: "Hello",
1024                    field2: 47
1025                }
1026            }
1027        "#;
1028        let result: TestNestedStruct = super::from_script(script).unwrap();
1029        assert_eq!(
1030            result,
1031            TestNestedStruct {
1032                nested: TestStruct {
1033                    field1: "Hello".to_string(),
1034                    field2: 47
1035                }
1036            }
1037        );
1038    }
1039
1040    #[test]
1041    fn struct_from_bytes() {
1042        let data = to_bytes(&TestStruct {
1043            field1: "Hello".to_string(),
1044            field2: 42,
1045        })
1046        .unwrap();
1047        let result: TestStruct = from_bytes(&data).unwrap();
1048        assert!(!result.field1.is_empty());
1049    }
1050
1051    #[test]
1052    fn from_script() {
1053        let script = r#"
1054            {
1055                field1: "Hello",
1056                field2: 42 + 5 // This will be evaluated to 47
1057            }
1058        "#;
1059        let result: TestStruct = super::from_script(script).unwrap();
1060        assert!(!result.field1.is_empty());
1061    }
1062
1063    #[test]
1064    fn test_from_static_script() {
1065        let script = r#"
1066            {
1067                field1: "Hello",
1068                field2: 42
1069            }
1070        "#;
1071        let result: TestStruct = from_static_script(script).unwrap();
1072        assert!(!result.field1.is_empty());
1073    }
1074
1075    #[test]
1076    fn enum_1() {
1077        let script = r#""Variant1""#;
1078        let dxb = compile_script(script, CompileOptions::default())
1079            .expect("Failed to compile script")
1080            .0;
1081        let result: TestEnum =
1082            from_bytes(&dxb).expect("Failed to deserialize TestEnum");
1083        assert!(core::matches!(result, TestEnum::Variant1));
1084    }
1085
1086    #[test]
1087    fn enum_2() {
1088        let script = r#""Variant2""#;
1089        let dxb = compile_script(script, CompileOptions::default())
1090            .expect("Failed to compile script")
1091            .0;
1092        let result: TestEnum =
1093            from_bytes(&dxb).expect("Failed to deserialize TestEnum");
1094        assert!(core::matches!(result, TestEnum::Variant2));
1095    }
1096
1097    #[test]
1098    fn struct_with_enum() {
1099        let script = r#"
1100            {
1101                test_enum: "Variant1"
1102            }
1103        "#;
1104        let dxb = compile_script(script, CompileOptions::default())
1105            .expect("Failed to compile script")
1106            .0;
1107        let result: TestStruct2 =
1108            from_bytes(&dxb).expect("Failed to deserialize TestStruct2");
1109        assert!(core::matches!(result.test_enum, TestEnum::Variant1));
1110    }
1111
1112    #[test]
1113    fn endpoint() {
1114        let script = r#"
1115            {
1116                endpoint: @jonas
1117            }
1118        "#;
1119        let dxb = compile_script(script, CompileOptions::default())
1120            .expect("Failed to compile script")
1121            .0;
1122        let result: TestStructWithEndpoint = from_bytes(&dxb)
1123            .expect("Failed to deserialize TestStructWithEndpoint");
1124        assert_eq!(result.endpoint.to_string(), "@jonas");
1125    }
1126
1127    #[test]
1128    fn optional_field() {
1129        let script = r#"
1130            {
1131                optional_field: "Optional Value"
1132            }
1133        "#;
1134        let dxb = compile_script(script, CompileOptions::default())
1135            .expect("Failed to compile script")
1136            .0;
1137        let result: TestWithOptionalField = from_bytes(&dxb)
1138            .expect("Failed to deserialize TestWithOptionalField");
1139        assert!(result.optional_field.is_some());
1140        assert_eq!(result.optional_field.unwrap(), "Optional Value");
1141    }
1142
1143    #[test]
1144    fn optional_field_empty() {
1145        let script = r#"
1146            {
1147                optional_field: null
1148            }
1149        "#;
1150        let dxb = compile_script(script, CompileOptions::default())
1151            .expect("Failed to compile script")
1152            .0;
1153        let result: TestWithOptionalField = from_bytes(&dxb)
1154            .expect("Failed to deserialize TestWithOptionalField");
1155        assert!(result.optional_field.is_none());
1156    }
1157
1158    #[test]
1159    fn optional_endpoint() {
1160        let script = r#"
1161            {
1162                endpoint: @jonas
1163            }
1164        "#;
1165        let dxb = compile_script(script, CompileOptions::default())
1166            .expect("Failed to compile script")
1167            .0;
1168        let result: TestStructWithOptionalEndpoint = from_bytes(&dxb)
1169            .expect("Failed to deserialize TestStructWithOptionalEndpoint");
1170        assert!(result.endpoint.is_some());
1171        assert_eq!(result.endpoint.unwrap().to_string(), "@jonas");
1172    }
1173
1174    #[derive(Deserialize, Serialize, Debug)]
1175    enum ExampleEnum {
1176        Variant1(String),
1177        Variant2(i32),
1178    }
1179
1180    #[test]
1181    fn map() {
1182        let script = "{Variant1: \"Hello\"}";
1183        let dxb = compile_script(script, CompileOptions::default())
1184            .expect("Failed to compile script")
1185            .0;
1186        let result: ExampleEnum =
1187            from_bytes(&dxb).expect("Failed to deserialize ExampleEnum");
1188        assert!(core::matches!(result, ExampleEnum::Variant1(_)));
1189
1190        let script = r#"{"Variant2": 42}"#;
1191        let dxb = compile_script(script, CompileOptions::default())
1192            .expect("Failed to compile script")
1193            .0;
1194        let result: ExampleEnum =
1195            from_bytes(&dxb).expect("Failed to deserialize ExampleEnum");
1196        assert!(core::matches!(result, ExampleEnum::Variant2(_)));
1197    }
1198}