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