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