datex_core/values/serde/
deserializer.rs

1use crate::{
2    compiler::{
3        CompileOptions, compile_script, extract_static_value_from_script,
4    },
5    runtime::execution::{ExecutionInput, ExecutionOptions, execute_dxb_sync},
6    values::{
7        core_value::CoreValue,
8        core_values::integer::{integer::Integer, typed_integer::TypedInteger},
9        serde::error::SerializationError,
10        value,
11        value_container::ValueContainer,
12    },
13};
14use serde::de::{DeserializeSeed, EnumAccess, VariantAccess, Visitor};
15use serde::{
16    Deserialize, Deserializer, de::IntoDeserializer, forward_to_deserialize_any,
17};
18use std::path::PathBuf;
19
20#[derive(Clone)]
21pub struct DatexDeserializer {
22    pub value: ValueContainer,
23}
24
25impl<'de> DatexDeserializer {
26    pub fn from_bytes(input: &'de [u8]) -> Result<Self, SerializationError> {
27        let context = ExecutionInput::new_with_dxb_and_options(
28            input,
29            ExecutionOptions { verbose: true },
30        );
31        let value = execute_dxb_sync(context)
32            .unwrap_or_else(|err| {
33                panic!("Execution failed: {err}");
34            })
35            .unwrap();
36        Ok(Self { value })
37    }
38
39    pub fn from_dx_file(path: PathBuf) -> Result<Self, SerializationError> {
40        let input = std::fs::read_to_string(path)
41            .map_err(|err| SerializationError(err.to_string()))?;
42        DatexDeserializer::from_script(&input)
43    }
44    pub fn from_dxb_file(path: PathBuf) -> Result<Self, SerializationError> {
45        let input = std::fs::read(path)
46            .map_err(|err| SerializationError(err.to_string()))?;
47        DatexDeserializer::from_bytes(&input)
48    }
49
50    pub fn from_script(script: &'de str) -> Result<Self, SerializationError> {
51        let (dxb, _) = compile_script(script, CompileOptions::default())
52            .map_err(|err| SerializationError(err.to_string()))?;
53        DatexDeserializer::from_bytes(&dxb)
54    }
55    pub fn from_static_script(
56        script: &'de str,
57    ) -> Result<Self, SerializationError> {
58        let value = extract_static_value_from_script(script)
59            .map_err(|err| SerializationError(err.to_string()))?;
60        if value.is_none() {
61            return Err(SerializationError(
62                "No static value found in script".to_string(),
63            ));
64        }
65        Ok(DatexDeserializer::from_value(value.unwrap()))
66    }
67
68    fn from_value(value: ValueContainer) -> Self {
69        Self { value }
70    }
71}
72impl<'de> IntoDeserializer<'de, SerializationError> for DatexDeserializer {
73    type Deserializer = Self;
74
75    fn into_deserializer(self) -> Self::Deserializer {
76        self
77    }
78}
79impl<'de> Deserializer<'de> for DatexDeserializer {
80    type Error = SerializationError;
81
82    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
83    where
84        V: serde::de::Visitor<'de>,
85    {
86        match self.value {
87            // TODO #148 implement missing mapping
88            ValueContainer::Value(value::Value { inner, .. }) => match inner {
89                CoreValue::Null => visitor.visit_none(),
90                CoreValue::Bool(b) => visitor.visit_bool(b.0),
91                CoreValue::TypedInteger(i) => match i {
92                    TypedInteger::I128(i) => visitor.visit_i128(i),
93                    TypedInteger::U128(u) => visitor.visit_u128(u),
94                    TypedInteger::I64(i) => visitor.visit_i64(i),
95                    TypedInteger::U64(u) => visitor.visit_u64(u),
96                    TypedInteger::I32(i) => visitor.visit_i32(i),
97                    TypedInteger::U32(u) => visitor.visit_u32(u),
98                    TypedInteger::I16(i) => visitor.visit_i16(i),
99                    TypedInteger::U16(u) => visitor.visit_u16(u),
100                    TypedInteger::I8(i) => visitor.visit_i8(i),
101                    TypedInteger::U8(u) => visitor.visit_u8(u),
102                    _ => unreachable!(),
103                },
104                CoreValue::Integer(Integer {
105                    0: TypedInteger::I128(i),
106                }) => visitor.visit_i128(i),
107                CoreValue::Integer(Integer {
108                    0: TypedInteger::U128(u),
109                }) => visitor.visit_u128(u),
110                CoreValue::Integer(Integer {
111                    0: TypedInteger::I64(i),
112                }) => visitor.visit_i64(i),
113                CoreValue::Integer(Integer {
114                    0: TypedInteger::U64(u),
115                }) => visitor.visit_u64(u),
116                CoreValue::Integer(Integer {
117                    0: TypedInteger::I32(i),
118                }) => visitor.visit_i32(i),
119                CoreValue::Integer(Integer {
120                    0: TypedInteger::U32(u),
121                }) => visitor.visit_u32(u),
122                CoreValue::Integer(Integer {
123                    0: TypedInteger::I16(i),
124                }) => visitor.visit_i16(i),
125                CoreValue::Integer(Integer {
126                    0: TypedInteger::U16(u),
127                }) => visitor.visit_u16(u),
128                CoreValue::Integer(Integer {
129                    0: TypedInteger::I8(i),
130                }) => visitor.visit_i8(i),
131                CoreValue::Integer(Integer {
132                    0: TypedInteger::U8(u),
133                }) => visitor.visit_u8(u),
134                CoreValue::Text(s) => visitor.visit_string(s.0),
135                CoreValue::Endpoint(endpoint) => {
136                    let endpoint_str = endpoint.to_string();
137                    visitor.visit_string(endpoint_str)
138                }
139                CoreValue::Object(obj) => {
140                    let map = obj
141                        .into_iter()
142                        .map(|(k, v)| (k, DatexDeserializer::from_value(v)));
143                    visitor
144                        .visit_map(serde::de::value::MapDeserializer::new(map))
145                }
146                CoreValue::Array(arr) => {
147                    let vec =
148                        arr.into_iter().map(DatexDeserializer::from_value);
149                    visitor
150                        .visit_seq(serde::de::value::SeqDeserializer::new(vec))
151                }
152                CoreValue::Tuple(tuple) => {
153                    let vec = tuple
154                        .into_iter()
155                        .map(|(_, v)| DatexDeserializer::from_value(v));
156                    visitor
157                        .visit_seq(serde::de::value::SeqDeserializer::new(vec))
158                }
159                e => unreachable!("Unsupported core value: {:?}", e),
160            },
161            _ => unreachable!("Refs are not supported in deserialization"),
162        }
163    }
164
165    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
166    where
167        V: serde::de::Visitor<'de>,
168    {
169        if self.value.to_value().borrow().is_null() {
170            visitor.visit_none()
171        } else {
172            visitor.visit_some(self)
173        }
174    }
175
176    forward_to_deserialize_any! {
177        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes byte_buf
178        tuple seq unit unit_struct struct ignored_any
179    }
180
181    fn deserialize_newtype_struct<V>(
182        self,
183        name: &'static str,
184        visitor: V,
185    ) -> Result<V::Value, Self::Error>
186    where
187        V: Visitor<'de>,
188    {
189        if let ValueContainer::Value(value::Value {
190            inner: CoreValue::Tuple(t),
191            ..
192        }) = self.value
193        {
194            let values =
195                t.into_iter().map(|(_, v)| DatexDeserializer::from_value(v));
196            visitor.visit_seq(serde::de::value::SeqDeserializer::new(values))
197        } else {
198            visitor.visit_seq(serde::de::value::SeqDeserializer::new(
199                vec![self.value.clone()]
200                    .into_iter()
201                    .map(DatexDeserializer::from_value),
202            ))
203        }
204    }
205    fn deserialize_tuple_struct<V>(
206        self,
207        name: &'static str,
208        len: usize,
209        visitor: V,
210    ) -> Result<V::Value, Self::Error>
211    where
212        V: Visitor<'de>,
213    {
214        if let ValueContainer::Value(value::Value {
215            inner: CoreValue::Tuple(t),
216            ..
217        }) = self.value
218        {
219            let values =
220                t.into_iter().map(|(_, v)| DatexDeserializer::from_value(v));
221            visitor.visit_seq(serde::de::value::SeqDeserializer::new(values))
222        } else {
223            visitor.visit_seq(serde::de::value::SeqDeserializer::new(
224                vec![self.value.clone()]
225                    .into_iter()
226                    .map(DatexDeserializer::from_value),
227            ))
228        }
229    }
230
231    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
232    where
233        V: Visitor<'de>,
234    {
235        todo!("#235 map")
236    }
237    fn deserialize_identifier<V>(
238        self,
239        visitor: V,
240    ) -> Result<V::Value, Self::Error>
241    where
242        V: Visitor<'de>,
243    {
244        println!("Deserializing identifier: {:?}", self.value);
245        // match tuple (Identifier, ValueContainer)
246        if let ValueContainer::Value(value::Value {
247            inner: CoreValue::Tuple(t),
248            ..
249        }) = self.value
250        {
251            let identifier = t
252                .at(0)
253                .ok_or(SerializationError("Invalid tuple".to_string()))?
254                .1;
255            visitor
256                .visit_string(identifier.to_value().borrow().cast_to_text().0)
257        }
258        // match string
259        else if let ValueContainer::Value(value::Value {
260            inner: CoreValue::Text(s),
261            ..
262        }) = self.value
263        {
264            visitor.visit_string(s.0)
265        } else {
266            Err(SerializationError("Expected identifier tuple".to_string()))
267        }
268    }
269
270    fn deserialize_enum<V>(
271        self,
272        _name: &str,
273        _variants: &'static [&'static str],
274        visitor: V,
275    ) -> Result<V::Value, Self::Error>
276    where
277        V: serde::de::Visitor<'de>,
278    {
279        println!("Deserializing enum: {:?}", self.value);
280        visitor.visit_enum(DatexEnumAccess { de: self })
281    }
282
283    fn is_human_readable(&self) -> bool {
284        false
285    }
286}
287
288struct DatexEnumAccess {
289    de: DatexDeserializer,
290}
291
292impl<'de> EnumAccess<'de> for DatexEnumAccess {
293    type Error = SerializationError;
294    type Variant = DatexVariantAccess;
295
296    fn variant_seed<V>(
297        self,
298        seed: V,
299    ) -> Result<(V::Value, Self::Variant), Self::Error>
300    where
301        V: DeserializeSeed<'de>,
302    {
303        let variant = seed.deserialize(self.de.clone())?;
304        Ok((variant, DatexVariantAccess { de: self.de }))
305    }
306}
307
308struct DatexVariantAccess {
309    de: DatexDeserializer,
310}
311impl<'de> VariantAccess<'de> for DatexVariantAccess {
312    type Error = SerializationError;
313
314    fn unit_variant(self) -> Result<(), Self::Error> {
315        Ok(())
316    }
317
318    fn newtype_variant_seed<T>(
319        mut self,
320        seed: T,
321    ) -> Result<T::Value, Self::Error>
322    where
323        T: DeserializeSeed<'de>,
324    {
325        if let ValueContainer::Value(value::Value {
326            inner: CoreValue::Tuple(t),
327            ..
328        }) = self.de.value
329        {
330            let value = t
331                .at(1)
332                .ok_or(SerializationError("Invalid tuple".to_string()))?
333                .1;
334            self.de.value = value.clone();
335            Ok(seed.deserialize(self.de)?)
336        } else {
337            Err(SerializationError("Expected identifier tuple".to_string()))
338        }
339    }
340
341    fn tuple_variant<V>(
342        self,
343        len: usize,
344        visitor: V,
345    ) -> Result<V::Value, Self::Error>
346    where
347        V: Visitor<'de>,
348    {
349        todo!("#236 Undescribed by author.")
350    }
351
352    fn struct_variant<V>(
353        self,
354        fields: &'static [&'static str],
355        visitor: V,
356    ) -> Result<V::Value, Self::Error>
357    where
358        V: Visitor<'de>,
359    {
360        todo!("#237 Undescribed by author.")
361    }
362}
363
364pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result<T, SerializationError>
365where
366    T: serde::Deserialize<'de>,
367{
368    let deserializer = DatexDeserializer::from_bytes(input)?;
369    T::deserialize(deserializer)
370}
371
372pub fn from_value_container<'de, T>(
373    value: ValueContainer,
374) -> Result<T, SerializationError>
375where
376    T: serde::Deserialize<'de>,
377{
378    let deserializer = DatexDeserializer::from_value(value);
379    T::deserialize(deserializer)
380}
381
382#[cfg(test)]
383mod tests {
384    use super::*;
385    use crate::values::serde::serializer::to_bytes;
386    use serde::{Deserialize, Serialize};
387    use crate::values::core_values::endpoint::Endpoint;
388
389    #[derive(Deserialize, Serialize, Debug, PartialEq)]
390    struct TestStruct {
391        field1: String,
392        field2: i32,
393    }
394
395    #[derive(Deserialize, Serialize, Debug)]
396    enum TestEnum {
397        Variant1,
398        Variant2,
399    }
400
401    #[derive(Deserialize, Serialize, Debug)]
402    struct TestStruct2 {
403        test_enum: TestEnum,
404    }
405
406    #[derive(Deserialize, Serialize, Debug)]
407    struct TestWithOptionalField {
408        optional_field: Option<String>,
409    }
410
411    #[derive(Deserialize)]
412    struct TestStructWithEndpoint {
413        endpoint: Endpoint,
414    }
415
416    #[derive(Deserialize)]
417    struct TestStructWithOptionalEndpoint {
418        endpoint: Option<Endpoint>,
419    }
420
421    #[derive(Deserialize, Serialize, Debug, PartialEq)]
422    struct TestNestedStruct {
423        nested: TestStruct,
424    }
425
426    #[test]
427    fn test_nested_struct_serde() {
428        let script = r#"
429            {
430                nested: {
431                    field1: "Hello",
432                    field2: 47
433                }
434            }
435        "#;
436        let deserializer = DatexDeserializer::from_script(script).unwrap();
437        let result: TestNestedStruct =
438            Deserialize::deserialize(deserializer).unwrap();
439        assert_eq!(
440            result,
441            TestNestedStruct {
442                nested: TestStruct {
443                    field1: "Hello".to_string(),
444                    field2: 47
445                }
446            }
447        );
448    }
449
450    #[test]
451    fn test_from_bytes() {
452        let data = to_bytes(&TestStruct {
453            field1: "Hello".to_string(),
454            field2: 42,
455        })
456        .unwrap();
457        let result: TestStruct = from_bytes(&data).unwrap();
458        assert!(!result.field1.is_empty());
459    }
460
461    #[test]
462    fn test_from_script() {
463        let script = r#"
464            {
465                field1: "Hello",
466                field2: 42 + 5 // This will be evaluated to 47
467            }
468        "#;
469        let deserializer = DatexDeserializer::from_script(script).unwrap();
470        let result: TestStruct =
471            Deserialize::deserialize(deserializer).unwrap();
472        assert!(!result.field1.is_empty());
473    }
474
475    // FIXME #149 we are loosing the type information for integers here (i128 instead of i32 as in structure)
476    // what causes a invalid type: integer error on the serde deserialization
477    #[test]
478    #[ignore = "This test is currently failing due to type mismatch (i128 instead of i32)"]
479    fn test_from_static_script() {
480        let script = r#"
481            {
482                field1: "Hello",
483                field2: 42
484            }
485        "#;
486        let deserializer =
487            DatexDeserializer::from_static_script(script).unwrap();
488        let result: TestStruct =
489            Deserialize::deserialize(deserializer).unwrap();
490        assert!(!result.field1.is_empty());
491    }
492
493    #[test]
494    fn test_enum_1() {
495        let script = r#""Variant1""#;
496        let dxb = compile_script(script, CompileOptions::default())
497            .expect("Failed to compile script")
498            .0;
499        let deserializer = DatexDeserializer::from_bytes(&dxb)
500            .expect("Failed to create deserializer from DXB");
501        let result: TestEnum = Deserialize::deserialize(deserializer)
502            .expect("Failed to deserialize TestEnum");
503        assert!(matches!(result, TestEnum::Variant1));
504    }
505
506    #[test]
507    fn test_enum_2() {
508        let script = r#""Variant2""#;
509        let dxb = compile_script(script, CompileOptions::default())
510            .expect("Failed to compile script")
511            .0;
512        let deserializer = DatexDeserializer::from_bytes(&dxb)
513            .expect("Failed to create deserializer from DXB");
514        let result: TestEnum = Deserialize::deserialize(deserializer)
515            .expect("Failed to deserialize TestEnum");
516        assert!(matches!(result, TestEnum::Variant2));
517    }
518
519    #[test]
520    fn test_struct_with_enum() {
521        let script = r#"
522            {
523                test_enum: "Variant1"
524            }
525        "#;
526        let dxb = compile_script(script, CompileOptions::default())
527            .expect("Failed to compile script")
528            .0;
529        let deserializer = DatexDeserializer::from_bytes(&dxb)
530            .expect("Failed to create deserializer from DXB");
531        let result: TestStruct2 = Deserialize::deserialize(deserializer)
532            .expect("Failed to deserialize TestStruct2");
533        assert!(matches!(result.test_enum, TestEnum::Variant1));
534    }
535
536    #[test]
537    fn test_endpoint() {
538        let script = r#"
539            {
540                endpoint: @jonas
541            }
542        "#;
543        let dxb = compile_script(script, CompileOptions::default())
544            .expect("Failed to compile script")
545            .0;
546        let deserializer = DatexDeserializer::from_bytes(&dxb)
547            .expect("Failed to create deserializer from DXB");
548        let result: TestStructWithEndpoint =
549            Deserialize::deserialize(deserializer)
550                .expect("Failed to deserialize TestStructWithEndpoint");
551        assert_eq!(result.endpoint.to_string(), "@jonas");
552    }
553
554    #[test]
555    fn test_optional_field() {
556        let script = r#"
557            {
558                optional_field: "Optional Value"
559            }
560        "#;
561        let dxb = compile_script(script, CompileOptions::default())
562            .expect("Failed to compile script")
563            .0;
564        let deserializer = DatexDeserializer::from_bytes(&dxb)
565            .expect("Failed to create deserializer from DXB");
566        let result: TestWithOptionalField =
567            Deserialize::deserialize(deserializer)
568                .expect("Failed to deserialize TestWithOptionalField");
569        assert!(result.optional_field.is_some());
570        assert_eq!(result.optional_field.unwrap(), "Optional Value");
571    }
572
573    #[test]
574    fn test_optional_field_empty() {
575        let script = r#"
576            {
577                optional_field: null
578            }
579        "#;
580        let dxb = compile_script(script, CompileOptions::default())
581            .expect("Failed to compile script")
582            .0;
583        let deserializer = DatexDeserializer::from_bytes(&dxb)
584            .expect("Failed to create deserializer from DXB");
585        let result: TestWithOptionalField =
586            Deserialize::deserialize(deserializer)
587                .expect("Failed to deserialize TestWithOptionalField");
588        assert!(result.optional_field.is_none());
589    }
590
591    #[test]
592    fn test_optional_endpoint() {
593        let script = r#"
594            {
595                endpoint: @jonas
596            }
597        "#;
598        let dxb = compile_script(script, CompileOptions::default())
599            .expect("Failed to compile script")
600            .0;
601        let deserializer = DatexDeserializer::from_bytes(&dxb)
602            .expect("Failed to create deserializer from DXB");
603        let result: TestStructWithOptionalEndpoint =
604            Deserialize::deserialize(deserializer)
605                .expect("Failed to deserialize TestStructWithOptionalEndpoint");
606        assert!(result.endpoint.is_some());
607        assert_eq!(result.endpoint.unwrap().to_string(), "@jonas");
608    }
609
610    #[derive(Deserialize, Serialize, Debug)]
611    enum ExampleEnum {
612        Variant1(String),
613        Variant2(i32),
614    }
615
616    #[test]
617    fn test_map() {
618        let script = r#"("Variant1", "xy")"#;
619        let dxb = compile_script(script, CompileOptions::default())
620            .expect("Failed to compile script")
621            .0;
622        let deserializer = DatexDeserializer::from_bytes(&dxb)
623            .expect("Failed to create deserializer from DXB");
624        let result: ExampleEnum = Deserialize::deserialize(deserializer)
625            .expect("Failed to deserialize ExampleEnum");
626        match result {
627            ExampleEnum::Variant1(s) => assert_eq!(s, "xy"),
628            _ => panic!("Expected Variant1 with value 'xy'"),
629        }
630
631        let script = r#"("Variant2", 42)"#;
632        let dxb = compile_script(script, CompileOptions::default())
633            .expect("Failed to compile script")
634            .0;
635        let deserializer = DatexDeserializer::from_bytes(&dxb)
636            .expect("Failed to create deserializer from DXB");
637        let result: ExampleEnum = Deserialize::deserialize(deserializer)
638            .expect("Failed to deserialize ExampleEnum");
639        match result {
640            ExampleEnum::Variant2(i) => assert_eq!(i, 42),
641            _ => panic!("Expected Variant2 with value 42"),
642        }
643    }
644}