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        memory: &RefCell<Memory>,
237    ) -> Self {
238        match struct_def {
239            StructuralTypeDefinition::Null => DIFTypeRepresentation::Null,
240            StructuralTypeDefinition::Boolean(b) => {
241                DIFTypeRepresentation::Boolean(b.as_bool())
242            }
243            StructuralTypeDefinition::Integer(i) => {
244                // FIXME #392: this can overflow
245                DIFTypeRepresentation::Number(i.as_i128().unwrap() as f64)
246            }
247            StructuralTypeDefinition::TypedInteger(i) => {
248                DIFTypeRepresentation::Number(i.as_i128().unwrap() as f64)
249            }
250            StructuralTypeDefinition::Range((start, end)) => {
251                DIFTypeRepresentation::Array(vec![
252                    DIFType::from_type(start, memory),
253                    DIFType::from_type(end, memory),
254                ])
255            }
256            StructuralTypeDefinition::Decimal(d) => {
257                DIFTypeRepresentation::Number(d.into_f64())
258            }
259            StructuralTypeDefinition::TypedDecimal(d) => {
260                DIFTypeRepresentation::Number(d.as_f64())
261            }
262            StructuralTypeDefinition::Text(t) => {
263                DIFTypeRepresentation::String(t.0.clone())
264            }
265            StructuralTypeDefinition::Endpoint(endpoint) => {
266                DIFTypeRepresentation::String(endpoint.to_string())
267            }
268            StructuralTypeDefinition::List(arr) => {
269                DIFTypeRepresentation::Array(
270                    arr.iter().map(|v| DIFType::from_type(v, memory)).collect(),
271                )
272            }
273            StructuralTypeDefinition::Map(fields) => {
274                DIFTypeRepresentation::Map(
275                    fields
276                        .iter()
277                        .map(|(k, v)| {
278                            (
279                                DIFType::from_type(k, memory),
280                                DIFType::from_type(v, memory),
281                            )
282                        })
283                        .collect(),
284                )
285            }
286        }
287    }
288}
289
290impl Serialize for DIFValueRepresentation {
291    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
292    where
293        S: Serializer,
294    {
295        match self {
296            DIFValueRepresentation::Null => serializer.serialize_unit(),
297            DIFValueRepresentation::Boolean(b) => serializer.serialize_bool(*b),
298            DIFValueRepresentation::String(s) => serializer.serialize_str(s),
299            DIFValueRepresentation::Number(f) => serializer.serialize_f64(*f),
300            DIFValueRepresentation::Array(vec) => vec.serialize(serializer),
301            DIFValueRepresentation::Map(entries) => {
302                let mut seq = serializer.serialize_seq(Some(entries.len()))?;
303                for (k, v) in entries {
304                    seq.serialize_element(&vec![k, v])?;
305                }
306                seq.end()
307            }
308            DIFValueRepresentation::Object(fields) => {
309                let mut map = serializer.serialize_map(Some(fields.len()))?;
310                for (k, v) in fields {
311                    map.serialize_entry(k, v)?;
312                }
313                map.end()
314            }
315        }
316    }
317}
318
319impl<'de> Deserialize<'de> for DIFValueRepresentation {
320    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
321    where
322        D: Deserializer<'de>,
323    {
324        struct DIFCoreValueVisitor;
325
326        impl<'de> Visitor<'de> for DIFCoreValueVisitor {
327            type Value = DIFValueRepresentation;
328
329            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
330                formatter.write_str("a valid DIFCoreValue")
331            }
332
333            fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
334                Ok(DIFValueRepresentation::Boolean(value))
335            }
336
337            fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
338                Ok(DIFValueRepresentation::Number(value as f64))
339            }
340
341            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
342                // Safe cast since DIFCoreValue uses i64
343                Ok(DIFValueRepresentation::Number(value as f64))
344            }
345
346            fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
347                Ok(DIFValueRepresentation::Number(value))
348            }
349
350            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
351            where
352                E: de::Error,
353            {
354                Ok(DIFValueRepresentation::String(value.to_string()))
355            }
356
357            fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
358                Ok(DIFValueRepresentation::String(value))
359            }
360
361            fn visit_none<E>(self) -> Result<Self::Value, E> {
362                Ok(DIFValueRepresentation::Null)
363            }
364
365            fn visit_unit<E>(self) -> Result<Self::Value, E> {
366                Ok(DIFValueRepresentation::Null)
367            }
368
369            // array / map
370            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
371            where
372                A: SeqAccess<'de>,
373            {
374                let first_entry = seq
375                    .next_element::<DeserializeMapOrArray<DIFValueContainer>>(
376                    )?;
377                match first_entry {
378                    Some(DeserializeMapOrArray::ArrayEntry(first)) => {
379                        let mut elements = vec![first];
380                        while let Some(elem) =
381                            seq.next_element::<DIFValueContainer>()?
382                        {
383                            elements.push(elem);
384                        }
385                        Ok(DIFValueRepresentation::Array(elements))
386                    }
387                    Some(DeserializeMapOrArray::MapEntry(k, v)) => {
388                        let mut elements = vec![(k, v)];
389                        while let Some((k, v)) = seq.next_element::<(
390                            DIFValueContainer,
391                            DIFValueContainer,
392                        )>(
393                        )? {
394                            elements.push((k, v));
395                        }
396                        Ok(DIFValueRepresentation::Map(elements))
397                    }
398                    None => Ok(DIFValueRepresentation::Array(vec![])), // empty array
399                }
400            }
401
402            // object
403            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
404            where
405                A: MapAccess<'de>,
406            {
407                let mut entries = Vec::new();
408                while let Some((k, v)) = map.next_entry()? {
409                    entries.push((k, v));
410                }
411                Ok(DIFValueRepresentation::Object(entries))
412            }
413        }
414
415        deserializer.deserialize_any(DIFCoreValueVisitor)
416    }
417}
418
419impl Serialize for DIFTypeRepresentation {
420    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
421    where
422        S: Serializer,
423    {
424        match self {
425            DIFTypeRepresentation::Null => serializer.serialize_unit(),
426            DIFTypeRepresentation::Boolean(b) => serializer.serialize_bool(*b),
427            DIFTypeRepresentation::String(s) => serializer.serialize_str(s),
428            DIFTypeRepresentation::Number(f) => serializer.serialize_f64(*f),
429            DIFTypeRepresentation::Array(vec) => vec.serialize(serializer),
430            DIFTypeRepresentation::Map(entries) => {
431                let mut seq = serializer.serialize_seq(Some(entries.len()))?;
432                for (k, v) in entries {
433                    seq.serialize_element(&vec![k, v])?;
434                }
435                seq.end()
436            }
437            DIFTypeRepresentation::Object(fields) => {
438                let mut map = serializer.serialize_map(Some(fields.len()))?;
439                for (k, v) in fields {
440                    map.serialize_entry(k, v)?;
441                }
442                map.end()
443            }
444        }
445    }
446}
447
448impl<'de> Deserialize<'de> for DIFTypeRepresentation {
449    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
450    where
451        D: Deserializer<'de>,
452    {
453        struct DIFCoreValueVisitor;
454
455        impl<'de> Visitor<'de> for DIFCoreValueVisitor {
456            type Value = DIFTypeRepresentation;
457
458            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
459                formatter.write_str("a valid DIFCoreValue")
460            }
461
462            fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E> {
463                Ok(DIFTypeRepresentation::Boolean(value))
464            }
465
466            fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E> {
467                Ok(DIFTypeRepresentation::Number(value as f64))
468            }
469
470            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
471                // Safe cast since DIFCoreValue uses i64
472                Ok(DIFTypeRepresentation::Number(value as f64))
473            }
474
475            fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> {
476                Ok(DIFTypeRepresentation::Number(value))
477            }
478
479            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
480            where
481                E: de::Error,
482            {
483                Ok(DIFTypeRepresentation::String(value.to_string()))
484            }
485
486            fn visit_string<E>(self, value: String) -> Result<Self::Value, E> {
487                Ok(DIFTypeRepresentation::String(value))
488            }
489
490            fn visit_none<E>(self) -> Result<Self::Value, E> {
491                Ok(DIFTypeRepresentation::Null)
492            }
493
494            fn visit_unit<E>(self) -> Result<Self::Value, E> {
495                Ok(DIFTypeRepresentation::Null)
496            }
497
498            // array / map
499            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
500            where
501                A: SeqAccess<'de>,
502            {
503                let first_entry =
504                    seq.next_element::<DeserializeMapOrArray<DIFType>>()?;
505                match first_entry {
506                    Some(DeserializeMapOrArray::ArrayEntry(first)) => {
507                        let mut elements = vec![first];
508                        while let Some(elem) = seq.next_element::<DIFType>()? {
509                            elements.push(elem);
510                        }
511                        Ok(DIFTypeRepresentation::Array(elements))
512                    }
513                    Some(DeserializeMapOrArray::MapEntry(k, v)) => {
514                        let mut elements = vec![(k, v)];
515                        while let Some((k, v)) =
516                            seq.next_element::<(DIFType, DIFType)>()?
517                        {
518                            elements.push((k, v));
519                        }
520                        Ok(DIFTypeRepresentation::Map(elements))
521                    }
522                    None => Ok(DIFTypeRepresentation::Array(vec![])), // empty array
523                }
524            }
525
526            // object
527            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
528            where
529                A: MapAccess<'de>,
530            {
531                let mut entries = Vec::new();
532                while let Some((k, v)) = map.next_entry()? {
533                    entries.push((k, v));
534                }
535                Ok(DIFTypeRepresentation::Object(entries))
536            }
537        }
538
539        deserializer.deserialize_any(DIFCoreValueVisitor)
540    }
541}