drasi_core/models/
element_value.rs

1#![allow(clippy::unwrap_used)]
2// Copyright 2024 The Drasi Authors.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::ConversionError;
17
18use std::{
19    collections::BTreeMap,
20    ops::{Index, IndexMut},
21};
22
23use crate::evaluation::variable_value::{float::Float, integer::Integer, VariableValue};
24
25use std::sync::Arc;
26
27use ordered_float::OrderedFloat;
28
29#[derive(Debug, Clone, Hash, Eq, PartialEq, Default)]
30pub enum ElementValue {
31    #[default]
32    Null,
33    Bool(bool),
34    Float(OrderedFloat<f64>),
35    Integer(i64),
36    String(Arc<str>),
37    List(Vec<ElementValue>),
38    Object(ElementPropertyMap),
39}
40
41impl From<&ElementPropertyMap> for VariableValue {
42    fn from(val: &ElementPropertyMap) -> Self {
43        let mut map = BTreeMap::new();
44        for (key, value) in val.values.iter() {
45            map.insert(key.to_string(), value.into());
46        }
47        VariableValue::Object(map)
48    }
49}
50
51impl From<&ElementValue> for VariableValue {
52    fn from(val: &ElementValue) -> Self {
53        match val {
54            ElementValue::Null => VariableValue::Null,
55            ElementValue::Bool(b) => VariableValue::Bool(*b),
56            ElementValue::Float(f) => VariableValue::Float(Float::from(f.0)),
57            ElementValue::Integer(i) => VariableValue::Integer(Integer::from(*i)),
58            ElementValue::String(s) => VariableValue::String(s.to_string()),
59            ElementValue::List(l) => VariableValue::List(l.iter().map(|x| x.into()).collect()),
60            ElementValue::Object(o) => o.into(),
61        }
62    }
63}
64
65impl TryInto<ElementValue> for &VariableValue {
66    type Error = ConversionError;
67
68    fn try_into(self) -> Result<ElementValue, ConversionError> {
69        match self {
70            VariableValue::Null => Ok(ElementValue::Null),
71            VariableValue::Bool(b) => Ok(ElementValue::Bool(*b)),
72            VariableValue::Float(f) => Ok(ElementValue::Float(OrderedFloat(
73                f.as_f64().unwrap_or_default(),
74            ))),
75            VariableValue::Integer(i) => Ok(ElementValue::Integer(i.as_i64().unwrap_or_default())),
76            VariableValue::String(s) => Ok(ElementValue::String(Arc::from(s.as_str()))),
77            VariableValue::List(l) => Ok(ElementValue::List(
78                l.iter().map(|x| x.try_into().unwrap_or_default()).collect(),
79            )),
80            VariableValue::Object(o) => Ok(ElementValue::Object(o.into())),
81            _ => Err(ConversionError {}),
82        }
83    }
84}
85
86impl TryInto<ElementValue> for VariableValue {
87    type Error = ConversionError;
88
89    fn try_into(self) -> Result<ElementValue, ConversionError> {
90        match self {
91            VariableValue::Null => Ok(ElementValue::Null),
92            VariableValue::Bool(b) => Ok(ElementValue::Bool(b)),
93            VariableValue::Float(f) => Ok(ElementValue::Float(OrderedFloat(
94                f.as_f64().unwrap_or_default(),
95            ))),
96            VariableValue::Integer(i) => Ok(ElementValue::Integer(i.as_i64().unwrap_or_default())),
97            VariableValue::String(s) => Ok(ElementValue::String(Arc::from(s.as_str()))),
98            VariableValue::List(l) => Ok(ElementValue::List(
99                l.iter().map(|x| x.try_into().unwrap_or_default()).collect(),
100            )),
101            VariableValue::Object(o) => Ok(ElementValue::Object(o.into())),
102            _ => Err(ConversionError {}),
103        }
104    }
105}
106
107impl From<&ElementValue> for serde_json::Value {
108    fn from(val: &ElementValue) -> Self {
109        match val {
110            ElementValue::Null => serde_json::Value::Null,
111            ElementValue::Bool(b) => serde_json::Value::Bool(*b),
112            ElementValue::Float(f) => {
113                serde_json::Value::Number(serde_json::Number::from_f64(f.into_inner()).unwrap())
114            }
115            ElementValue::Integer(i) => serde_json::Value::Number(serde_json::Number::from(*i)),
116            ElementValue::String(s) => serde_json::Value::String(s.to_string()),
117            ElementValue::List(l) => serde_json::Value::Array(l.iter().map(|x| x.into()).collect()),
118            ElementValue::Object(o) => serde_json::Value::Object(o.into()),
119        }
120    }
121}
122
123impl From<&serde_json::Value> for ElementValue {
124    fn from(value: &serde_json::Value) -> Self {
125        match value {
126            serde_json::Value::Null => ElementValue::Null,
127            serde_json::Value::Bool(b) => ElementValue::Bool(*b),
128            serde_json::Value::Number(n) => {
129                if let Some(i) = n.as_i64() {
130                    ElementValue::Integer(i)
131                } else if let Some(f) = n.as_f64() {
132                    ElementValue::Float(OrderedFloat(f))
133                } else {
134                    ElementValue::Null
135                }
136            }
137            serde_json::Value::String(s) => ElementValue::String(Arc::from(s.as_str())),
138            serde_json::Value::Array(a) => ElementValue::List(a.iter().map(|x| x.into()).collect()),
139            serde_json::Value::Object(o) => ElementValue::Object(o.into()),
140        }
141    }
142}
143
144impl TryInto<ElementPropertyMap> for &VariableValue {
145    type Error = ConversionError;
146
147    fn try_into(self) -> Result<ElementPropertyMap, ConversionError> {
148        match self {
149            VariableValue::Object(o) => {
150                let mut values = BTreeMap::new();
151                for (key, value) in o.iter() {
152                    values.insert(Arc::from(key.as_str()), value.try_into()?);
153                }
154                Ok(ElementPropertyMap { values })
155            }
156            _ => Err(ConversionError {}),
157        }
158    }
159}
160
161#[derive(Debug, Clone, Hash, Eq, PartialEq)]
162pub struct ElementPropertyMap {
163    values: BTreeMap<Arc<str>, ElementValue>,
164}
165
166impl Default for ElementPropertyMap {
167    fn default() -> Self {
168        Self::new()
169    }
170}
171
172impl ElementPropertyMap {
173    pub fn new() -> Self {
174        ElementPropertyMap {
175            values: BTreeMap::new(),
176        }
177    }
178
179    pub fn get(&self, key: &str) -> Option<&ElementValue> {
180        self.values.get(key)
181    }
182
183    pub fn insert(&mut self, key: &str, value: ElementValue) {
184        self.values.insert(Arc::from(key), value);
185    }
186
187    pub fn merge(&mut self, other: &ElementPropertyMap) {
188        for (key, value) in other.values.iter() {
189            self.values
190                .entry(key.clone())
191                .or_insert_with(|| value.clone());
192        }
193    }
194
195    pub fn map_iter<T>(
196        &self,
197        f: impl Fn(&Arc<str>, &ElementValue) -> T + 'static,
198    ) -> impl Iterator<Item = T> + '_ {
199        self.values.iter().map(move |(k, v)| f(k, v))
200    }
201}
202
203impl Index<&str> for ElementPropertyMap {
204    type Output = ElementValue;
205
206    fn index(&self, key: &str) -> &Self::Output {
207        static NULL: ElementValue = ElementValue::Null;
208        match self.values.get(key) {
209            Some(value) => value,
210            None => &NULL,
211        }
212    }
213}
214
215impl IndexMut<&str> for ElementPropertyMap {
216    fn index_mut(&mut self, key: &str) -> &mut Self::Output {
217        self.values
218            .entry(Arc::from(key))
219            .or_insert_with(|| ElementValue::Null)
220    }
221}
222
223impl From<&BTreeMap<String, VariableValue>> for ElementPropertyMap {
224    fn from(map: &BTreeMap<String, VariableValue>) -> Self {
225        let mut values = BTreeMap::new();
226        for (key, value) in map.iter() {
227            values.insert(Arc::from(key.as_str()), value.try_into().unwrap());
228        }
229        ElementPropertyMap { values }
230    }
231}
232
233impl From<BTreeMap<String, VariableValue>> for ElementPropertyMap {
234    fn from(map: BTreeMap<String, VariableValue>) -> Self {
235        let mut values = BTreeMap::new();
236        for (key, value) in map {
237            values.insert(Arc::from(key.as_str()), value.try_into().unwrap());
238        }
239        ElementPropertyMap { values }
240    }
241}
242
243impl From<BTreeMap<String, ElementValue>> for ElementPropertyMap {
244    fn from(map: BTreeMap<String, ElementValue>) -> Self {
245        let mut values = BTreeMap::new();
246        for (key, value) in map {
247            values.insert(Arc::from(key.as_str()), value);
248        }
249        ElementPropertyMap { values }
250    }
251}
252
253impl From<&ElementPropertyMap> for serde_json::Map<String, serde_json::Value> {
254    fn from(val: &ElementPropertyMap) -> Self {
255        val.values
256            .iter()
257            .map(|(k, v)| (k.to_string(), v.into()))
258            .collect()
259    }
260}
261
262impl From<&serde_json::Map<String, serde_json::Value>> for ElementPropertyMap {
263    fn from(map: &serde_json::Map<String, serde_json::Value>) -> Self {
264        let mut values = BTreeMap::new();
265        for (key, value) in map.iter() {
266            values.insert(Arc::from(key.as_str()), value.into());
267        }
268        ElementPropertyMap { values }
269    }
270}
271
272impl From<serde_json::Value> for ElementPropertyMap {
273    fn from(value: serde_json::Value) -> Self {
274        match value {
275            serde_json::Value::Object(o) => (&o).into(),
276            _ => ElementPropertyMap::new(),
277        }
278    }
279}
280
281impl From<&serde_json::Value> for ElementPropertyMap {
282    fn from(value: &serde_json::Value) -> Self {
283        match value {
284            serde_json::Value::Object(o) => o.into(),
285            _ => ElementPropertyMap::new(),
286        }
287    }
288}