datex_core/values/core_values/
tuple.rs

1use super::super::core_value_trait::CoreValueTrait;
2use crate::values::core_value::CoreValue;
3use crate::values::core_values::integer::typed_integer::TypedInteger;
4use crate::values::traits::structural_eq::StructuralEq;
5use crate::values::value::Value;
6use crate::values::value_container::ValueContainer;
7use indexmap::IndexMap;
8use indexmap::map::{IntoIter, Iter};
9use std::collections::HashMap;
10use std::fmt::{self, Display};
11use std::hash::{Hash, Hasher};
12
13#[derive(Clone, Debug, Default, Eq, PartialEq)]
14pub struct Tuple {
15    pub entries: IndexMap<ValueContainer, ValueContainer>,
16    next_int_key: u32,
17}
18impl Tuple {
19    pub fn default() -> Self {
20        Tuple {
21            entries: IndexMap::new(),
22            next_int_key: 0,
23        }
24    }
25    pub fn new(entries: IndexMap<ValueContainer, ValueContainer>) -> Self {
26        Tuple {
27            entries,
28            ..Tuple::default()
29        }
30    }
31
32    pub fn size(&self) -> usize {
33        self.entries.len()
34    }
35
36    /// returns the next integer key in the tuple, starting from 0
37    pub(crate) fn next_int_key(&self) -> u32 {
38        self.next_int_key
39    }
40
41    pub fn get(&self, key: &ValueContainer) -> Option<&ValueContainer> {
42        self.entries.get(key)
43    }
44    
45    pub fn at(&self, index: usize) -> Option<(&ValueContainer, &ValueContainer)> {
46        self.entries.get_index(index)
47    }
48
49    /// Set a key-value pair in the tuple. This method should only be used internal, since tuples
50    /// are immutable after creation as per DATEX specification.
51    pub(crate) fn set<K: Into<ValueContainer>, V: Into<ValueContainer>>(
52        &mut self,
53        key: K,
54        value: V,
55    ) {
56        let key = key.into();
57        // if key is integer and the expected next int key, increment the next_int_key
58        if let ValueContainer::Value(Value {
59            inner: CoreValue::Integer(typed_int),
60            ..
61        }) = key
62            && let Some(int) = typed_int.0.as_i128()
63            && int == self.next_int_key as i128
64        {
65            self.next_int_key += 1;
66        }
67        self.entries.insert(key, value.into());
68    }
69    pub fn insert<V: Into<ValueContainer>>(&mut self, value: V) {
70        self.entries
71            .insert(self.next_int_key().into(), value.into());
72        self.next_int_key += 1;
73    }
74}
75
76impl StructuralEq for Tuple {
77    fn structural_eq(&self, other: &Self) -> bool {
78        if self.size() != other.size() {
79            return false;
80        }
81        for ((key, value), (other_key, other_value)) in
82            self.entries.iter().zip(other.entries.iter())
83        {
84            if !key.structural_eq(other_key)
85                || !value.structural_eq(other_value)
86            {
87                return false;
88            }
89        }
90        true
91    }
92}
93
94impl Hash for Tuple {
95    fn hash<H: Hasher>(&self, state: &mut H) {
96        for (k, v) in &self.entries {
97            k.hash(state);
98            v.hash(state);
99        }
100    }
101}
102
103impl CoreValueTrait for Tuple {}
104
105impl Display for Tuple {
106    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107        write!(f, "(")?;
108        for (i, (key, value)) in self.entries.iter().enumerate() {
109            if i > 0 {
110                write!(f, ", ")?;
111            }
112            write!(f, "{key}: {value}")?;
113        }
114        write!(f, ")")
115    }
116}
117
118impl<K, V> From<HashMap<K, V>> for Tuple
119where
120    K: Into<ValueContainer>,
121    V: Into<ValueContainer>,
122{
123    fn from(map: HashMap<K, V>) -> Self {
124        Tuple::new(map.into_iter().map(|(k, v)| (k.into(), v.into())).collect())
125    }
126}
127
128impl<T> FromIterator<T> for Tuple
129where
130    T: Into<ValueContainer>,
131{
132    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
133        Tuple::new(
134            iter.into_iter()
135                .enumerate()
136                .map(|(i, v)| (TypedInteger::from(i as u64).into(), v.into()))
137                .collect(),
138        )
139    }
140}
141
142impl IntoIterator for Tuple {
143    type Item = (ValueContainer, ValueContainer);
144    type IntoIter = IntoIter<ValueContainer, ValueContainer>;
145
146    fn into_iter(self) -> Self::IntoIter {
147        self.entries.into_iter()
148    }
149}
150
151impl<'a> IntoIterator for &'a Tuple {
152    type Item = (&'a ValueContainer, &'a ValueContainer);
153    type IntoIter = Iter<'a, ValueContainer, ValueContainer>;
154
155    fn into_iter(self) -> Self::IntoIter {
156        self.entries.iter()
157    }
158}
159impl From<Vec<(ValueContainer, ValueContainer)>> for Tuple {
160    fn from(vec: Vec<(ValueContainer, ValueContainer)>) -> Self {
161        Tuple::new(vec.into_iter().collect())
162    }
163}
164
165impl From<IndexMap<ValueContainer, ValueContainer>> for Tuple {
166    fn from(map: IndexMap<ValueContainer, ValueContainer>) -> Self {
167        Tuple::new(map)
168    }
169}
170impl From<IndexMap<String, ValueContainer>> for Tuple {
171    fn from(map: IndexMap<String, ValueContainer>) -> Self {
172        Tuple::new(
173            map.into_iter()
174                .map(|(k, v)| (k.into(), v))
175                .collect::<IndexMap<ValueContainer, ValueContainer>>(),
176        )
177    }
178}
179impl TryFrom<CoreValue> for Tuple {
180    type Error = String;
181
182    fn try_from(value: CoreValue) -> Result<Self, Self::Error> {
183        if let CoreValue::Tuple(tuple) = value {
184            Ok(tuple)
185        } else {
186            Err(format!("Expected CoreValue::Tuple, found {value:?}"))
187        }
188    }
189}