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