Skip to main content

datex_core/dif/
representation.rs

1use crate::{
2    dif::{
3        r#type::{DIFType, DIFTypeDefinition},
4        value::{DIFReferenceNotFoundError, DIFValueContainer},
5    },
6    libs::core::{CoreLibPointerId, get_core_lib_type_definition},
7    runtime::memory::Memory,
8    types::structural_type_definition::StructuralTypeDefinition,
9    values::{
10        core_value::CoreValue,
11        core_values::{
12            decimal::typed_decimal::{DecimalTypeVariant, TypedDecimal},
13            integer::Integer,
14            map::Map,
15        },
16        value::Value,
17        value_container::ValueContainer,
18    },
19};
20
21use crate::{
22    prelude::*, values::core_values::integer::typed_integer::TypedInteger,
23};
24use core::{cell::RefCell, fmt, result::Result};
25use indexmap::IndexMap;
26use ordered_float::OrderedFloat;
27use serde::{
28    Deserialize, Deserializer, Serialize, Serializer, de,
29    de::{MapAccess, SeqAccess, Visitor},
30    ser::{SerializeMap, SerializeSeq},
31};
32
33#[derive(Clone, Debug, PartialEq)]
34pub enum DIFValueRepresentation {
35    Null,
36    /// Represents a boolean value in DIF.
37    Boolean(bool),
38    /// Represents a string value in DIF.
39    String(String),
40    /// Represents a number in DIF.
41    Number(f64),
42    /// Represents a array of DIF values.
43    Array(Vec<DIFValueContainer>),
44    /// Represents a map of DIF values.
45    Map(Vec<(DIFValueContainer, DIFValueContainer)>),
46    /// Represents a struct value in DIF.
47    Object(Vec<(String, DIFValueContainer)>),
48}
49
50#[derive(Clone, Debug, PartialEq)]
51pub enum DIFTypeRepresentation {
52    Null,
53    /// Represents a boolean value in DIF.
54    Boolean(bool),
55    /// Represents a string value in DIF.
56    String(String),
57    /// Represents a number in DIF.
58    Number(f64),
59    /// Represents a array of DIF values.
60    Array(Vec<DIFType>),
61    /// Represents a map of DIF values.
62    Map(Vec<(DIFType, DIFType)>),
63    /// Represents a struct value in DIF.
64    Object(Vec<(String, DIFType)>),
65}
66
67impl DIFValueRepresentation {
68    /// Converts a DIFRepresentationValue into a default Value, without considering additional type information.
69    /// Returns an error if a reference cannot be resolved.
70    pub fn to_default_value(
71        &self,
72        memory: &RefCell<Memory>,
73    ) -> Result<Value, DIFReferenceNotFoundError> {
74        Ok(match self {
75            DIFValueRepresentation::Null => Value::null(),
76            DIFValueRepresentation::String(str) => Value {
77                actual_type: Box::new(get_core_lib_type_definition(
78                    CoreLibPointerId::Text,
79                )),
80                inner: CoreValue::Text(str.clone().into()),
81            },
82            DIFValueRepresentation::Boolean(b) => Value {
83                actual_type: Box::new(get_core_lib_type_definition(
84                    CoreLibPointerId::Boolean,
85                )),
86                inner: CoreValue::Boolean((*b).into()),
87            },
88            DIFValueRepresentation::Number(n) => Value {
89                actual_type: Box::new(get_core_lib_type_definition(
90                    CoreLibPointerId::Decimal(Some(DecimalTypeVariant::F64)),
91                )),
92                inner: CoreValue::TypedDecimal(TypedDecimal::F64(
93                    OrderedFloat::from(*n),
94                )),
95            },
96            DIFValueRepresentation::Array(array) => Value {
97                actual_type: Box::new(get_core_lib_type_definition(
98                    CoreLibPointerId::List,
99                )),
100                inner: CoreValue::List(
101                    array
102                        .iter()
103                        .map(|v| v.to_value_container(memory))
104                        .collect::<Result<Vec<ValueContainer>, _>>()?
105                        .into(),
106                ),
107            },
108            DIFValueRepresentation::Object(object) => {
109                let mut map: Vec<(String, ValueContainer)> = Vec::new();
110                for (k, v) in object.clone() {
111                    map.push((k, v.to_value_container(memory)?));
112                }
113                Value {
114                    actual_type: Box::new(get_core_lib_type_definition(
115                        CoreLibPointerId::Map,
116                    )),
117                    inner: CoreValue::Map(map.into()),
118                }
119            }
120            DIFValueRepresentation::Map(map) => {
121                let mut core_map = IndexMap::default();
122                for (k, v) in map {
123                    core_map.insert(
124                        k.to_value_container(memory)?,
125                        v.to_value_container(memory)?,
126                    );
127                }
128                Value {
129                    actual_type: Box::new(get_core_lib_type_definition(
130                        CoreLibPointerId::Map,
131                    )),
132                    inner: CoreValue::Map(core_map.into()),
133                }
134            }
135            _ => {
136                core::todo!(
137                    "#388 Other DIFValueRepresentation variants not supported yet"
138                )
139            }
140        })
141    }
142
143    /// Converts a DIFValueRepresentation into a Value, using the provided type information to guide the conversion.
144    /// Returns an error if a reference cannot be resolved.
145    pub fn to_value_with_type(
146        &self,
147        type_definition: &DIFTypeDefinition,
148        memory: &RefCell<Memory>,
149    ) -> Result<Value, DIFReferenceNotFoundError> {
150        let val = match type_definition {
151            DIFTypeDefinition::Reference(r) => {
152                if let Ok(core_lib_ptr_id) = CoreLibPointerId::try_from(r) {
153                    match core_lib_ptr_id {
154                        // special mappings:
155                        // type map and represented as object -> convert to map
156                        CoreLibPointerId::Map
157                            if let DIFValueRepresentation::Object(object) =
158                                self =>
159                        {
160                            let mut entries: Vec<(String, ValueContainer)> =
161                                Vec::new();
162                            for (k, v) in object.clone().into_iter() {
163                                entries
164                                    .push((k, v.to_value_container(memory)?));
165                            }
166                            Some(Value::from(CoreValue::Map(Map::from(
167                                entries,
168                            ))))
169                        }
170                        // type map and represented as empty array -> convert to empty map
171                        CoreLibPointerId::Map
172                            if let DIFValueRepresentation::Array(array) =
173                                self =>
174                        {
175                            // assert that array is empty, otherwise this is not a valid DIF representation
176                            if !array.is_empty() {
177                                unreachable!(
178                                    "Invalid DIF value, non-empty array with map type"
179                                )
180                            }
181                            Some(Value::from(CoreValue::Map(Map::Structural(
182                                vec![],
183                            ))))
184                        }
185                        // type integer and represented as string -> convert to integer
186                        CoreLibPointerId::Integer(None)
187                            if let DIFValueRepresentation::String(s) = self =>
188                        {
189                            Some(Value::from(CoreValue::Integer(
190                                Integer::from_string(s).unwrap(),
191                            )))
192                        }
193                        CoreLibPointerId::Integer(Some(variant))
194                            if let DIFValueRepresentation::String(s) = self =>
195                        {
196                            Some(Value::from(CoreValue::TypedInteger(
197                                TypedInteger::from_string_with_variant(
198                                    s, variant,
199                                )
200                                .unwrap(),
201                            )))
202                        }
203                        // otherwise, use default mapping
204                        _ => None,
205                    }
206                } else {
207                    core::todo!("#389 Handle non-core library type references")
208                }
209            }
210            _ => None,
211        };
212        let val = match val {
213            Some(v) => v,
214            None => self.to_default_value(memory)?,
215        };
216
217        let ty = type_definition.to_type_definition(memory);
218
219        Ok(Value {
220            actual_type: Box::new(ty),
221            ..val
222        })
223    }
224}
225
226#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
227#[serde(untagged)]
228pub enum DeserializeMapOrArray<T> {
229    MapEntry(T, T),
230    ArrayEntry(T),
231}
232
233impl DIFTypeRepresentation {
234    pub fn from_structural_type_definition(
235        struct_def: &StructuralTypeDefinition,
236    ) -> Self {
237        match struct_def {
238            StructuralTypeDefinition::Null => DIFTypeRepresentation::Null,
239            StructuralTypeDefinition::Boolean(b) => {
240                DIFTypeRepresentation::Boolean(b.as_bool())
241            }
242            StructuralTypeDefinition::Integer(i) => {
243                // FIXME #392: this can overflow
244                DIFTypeRepresentation::Number(i.as_i128().unwrap() as f64)
245            }
246            StructuralTypeDefinition::TypedInteger(i) => {
247                DIFTypeRepresentation::Number(i.as_i128().unwrap() as f64)
248            }
249            StructuralTypeDefinition::Range((start, end)) => {
250                DIFTypeRepresentation::Array(vec![
251                    DIFType::from_type(start),
252                    DIFType::from_type(end),
253                ])
254            }
255            StructuralTypeDefinition::Decimal(d) => {
256                DIFTypeRepresentation::Number(d.into_f64())
257            }
258            StructuralTypeDefinition::TypedDecimal(d) => {
259                DIFTypeRepresentation::Number(d.as_f64())
260            }
261            StructuralTypeDefinition::Text(t) => {
262                DIFTypeRepresentation::String(t.0.clone())
263            }
264            StructuralTypeDefinition::Endpoint(endpoint) => {
265                DIFTypeRepresentation::String(endpoint.to_string())
266            }
267            StructuralTypeDefinition::List(arr) => {
268                DIFTypeRepresentation::Array(
269                    arr.iter().map(DIFType::from_type).collect(),
270                )
271            }
272            StructuralTypeDefinition::Map(fields) => {
273                DIFTypeRepresentation::Map(
274                    fields
275                        .iter()
276                        .map(|(k, v)| {
277                            (DIFType::from_type(k), DIFType::from_type(v))
278                        })
279                        .collect(),
280                )
281            }
282        }
283    }
284}
285
286impl Serialize for DIFValueRepresentation {
287    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
288    where
289        S: Serializer,
290    {
291        match self {
292            DIFValueRepresentation::Null => serializer.serialize_unit(),
293            DIFValueRepresentation::Boolean(b) => serializer.serialize_bool(*b),
294            DIFValueRepresentation::String(s) => serializer.serialize_str(s),
295            DIFValueRepresentation::Number(f) => serializer.serialize_f64(*f),
296            DIFValueRepresentation::Array(vec) => vec.serialize(serializer),
297            DIFValueRepresentation::Map(entries) => {
298                let mut seq = serializer.serialize_seq(Some(entries.len()))?;
299                for (k, v) in entries {
300                    seq.serialize_element(&vec![k, v])?;
301                }
302                seq.end()
303            }
304            DIFValueRepresentation::Object(fields) => {
305                let mut map = serializer.serialize_map(Some(fields.len()))?;
306                for (k, v) in fields {
307                    map.serialize_entry(k, v)?;
308                }
309                map.end()
310            }
311        }
312    }
313}
314
315impl<'de> Deserialize<'de> for DIFValueRepresentation {
316    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
317    where
318        D: Deserializer<'de>,
319    {
320        struct DIFCoreValueVisitor;
321
322        impl<'de> Visitor<'de> for DIFCoreValueVisitor {
323            type Value = DIFValueRepresentation;
324
325            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
326                formatter.write_str("a valid DIFCoreValue")
327            }
328
329            fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
330                Ok(DIFValueRepresentation::Boolean(value))
331            }
332
333            fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
334                Ok(DIFValueRepresentation::Number(value as f64))
335            }
336
337            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
338                // Safe cast since DIFCoreValue uses i64
339                Ok(DIFValueRepresentation::Number(value as f64))
340            }
341
342            fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
343                Ok(DIFValueRepresentation::Number(value))
344            }
345
346            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
347            where
348                E: de::Error,
349            {
350                Ok(DIFValueRepresentation::String(value.to_string()))
351            }
352
353            fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
354                Ok(DIFValueRepresentation::String(value))
355            }
356
357            fn visit_none<E>(self) -> Result<Self::Value, E> {
358                Ok(DIFValueRepresentation::Null)
359            }
360
361            fn visit_unit<E>(self) -> Result<Self::Value, E> {
362                Ok(DIFValueRepresentation::Null)
363            }
364
365            // array / map
366            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
367            where
368                A: SeqAccess<'de>,
369            {
370                let first_entry = seq
371                    .next_element::<DeserializeMapOrArray<DIFValueContainer>>(
372                    )?;
373                match first_entry {
374                    Some(DeserializeMapOrArray::ArrayEntry(first)) => {
375                        let mut elements = vec![first];
376                        while let Some(elem) =
377                            seq.next_element::<DIFValueContainer>()?
378                        {
379                            elements.push(elem);
380                        }
381                        Ok(DIFValueRepresentation::Array(elements))
382                    }
383                    Some(DeserializeMapOrArray::MapEntry(k, v)) => {
384                        let mut elements = vec![(k, v)];
385                        while let Some((k, v)) = seq.next_element::<(
386                            DIFValueContainer,
387                            DIFValueContainer,
388                        )>(
389                        )? {
390                            elements.push((k, v));
391                        }
392                        Ok(DIFValueRepresentation::Map(elements))
393                    }
394                    None => Ok(DIFValueRepresentation::Array(vec![])), // empty array
395                }
396            }
397
398            // object
399            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
400            where
401                A: MapAccess<'de>,
402            {
403                let mut entries = Vec::new();
404                while let Some((k, v)) = map.next_entry()? {
405                    entries.push((k, v));
406                }
407                Ok(DIFValueRepresentation::Object(entries))
408            }
409        }
410
411        deserializer.deserialize_any(DIFCoreValueVisitor)
412    }
413}
414
415impl Serialize for DIFTypeRepresentation {
416    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
417    where
418        S: Serializer,
419    {
420        match self {
421            DIFTypeRepresentation::Null => serializer.serialize_unit(),
422            DIFTypeRepresentation::Boolean(b) => serializer.serialize_bool(*b),
423            DIFTypeRepresentation::String(s) => serializer.serialize_str(s),
424            DIFTypeRepresentation::Number(f) => serializer.serialize_f64(*f),
425            DIFTypeRepresentation::Array(vec) => vec.serialize(serializer),
426            DIFTypeRepresentation::Map(entries) => {
427                let mut seq = serializer.serialize_seq(Some(entries.len()))?;
428                for (k, v) in entries {
429                    seq.serialize_element(&vec![k, v])?;
430                }
431                seq.end()
432            }
433            DIFTypeRepresentation::Object(fields) => {
434                let mut map = serializer.serialize_map(Some(fields.len()))?;
435                for (k, v) in fields {
436                    map.serialize_entry(k, v)?;
437                }
438                map.end()
439            }
440        }
441    }
442}
443
444impl<'de> Deserialize<'de> for DIFTypeRepresentation {
445    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
446    where
447        D: Deserializer<'de>,
448    {
449        struct DIFCoreValueVisitor;
450
451        impl<'de> Visitor<'de> for DIFCoreValueVisitor {
452            type Value = DIFTypeRepresentation;
453
454            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
455                formatter.write_str("a valid DIFCoreValue")
456            }
457
458            fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
459                Ok(DIFTypeRepresentation::Boolean(value))
460            }
461
462            fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
463                Ok(DIFTypeRepresentation::Number(value as f64))
464            }
465
466            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
467                // Safe cast since DIFCoreValue uses i64
468                Ok(DIFTypeRepresentation::Number(value as f64))
469            }
470
471            fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
472                Ok(DIFTypeRepresentation::Number(value))
473            }
474
475            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
476            where
477                E: de::Error,
478            {
479                Ok(DIFTypeRepresentation::String(value.to_string()))
480            }
481
482            fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
483                Ok(DIFTypeRepresentation::String(value))
484            }
485
486            fn visit_none<E>(self) -> Result<Self::Value, E> {
487                Ok(DIFTypeRepresentation::Null)
488            }
489
490            fn visit_unit<E>(self) -> Result<Self::Value, E> {
491                Ok(DIFTypeRepresentation::Null)
492            }
493
494            // array / map
495            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
496            where
497                A: SeqAccess<'de>,
498            {
499                let first_entry =
500                    seq.next_element::<DeserializeMapOrArray<DIFType>>()?;
501                match first_entry {
502                    Some(DeserializeMapOrArray::ArrayEntry(first)) => {
503                        let mut elements = vec![first];
504                        while let Some(elem) = seq.next_element::<DIFType>()? {
505                            elements.push(elem);
506                        }
507                        Ok(DIFTypeRepresentation::Array(elements))
508                    }
509                    Some(DeserializeMapOrArray::MapEntry(k, v)) => {
510                        let mut elements = vec![(k, v)];
511                        while let Some((k, v)) =
512                            seq.next_element::<(DIFType, DIFType)>()?
513                        {
514                            elements.push((k, v));
515                        }
516                        Ok(DIFTypeRepresentation::Map(elements))
517                    }
518                    None => Ok(DIFTypeRepresentation::Array(vec![])), // empty array
519                }
520            }
521
522            // object
523            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
524            where
525                A: MapAccess<'de>,
526            {
527                let mut entries = Vec::new();
528                while let Some((k, v)) = map.next_entry()? {
529                    entries.push((k, v));
530                }
531                Ok(DIFTypeRepresentation::Object(entries))
532            }
533        }
534
535        deserializer.deserialize_any(DIFCoreValueVisitor)
536    }
537}