drasi_core/evaluation/variable_value/
from.rs

1// Copyright 2024 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use super::VariableValue;
16extern crate alloc;
17use crate::evaluation::variable_value::float::Float;
18use crate::evaluation::variable_value::integer::Integer;
19use crate::evaluation::variable_value::zoned_datetime::ZonedDateTime;
20use crate::evaluation::variable_value::zoned_time::ZonedTime;
21use alloc::borrow::Cow;
22use chrono::{NaiveDate, NaiveTime};
23use serde_json::{Map, Value};
24use std::collections::BTreeMap;
25
26macro_rules! from_integer {
27    ($($ty:ident)*) => {
28        $(
29            impl From<$ty> for VariableValue {
30                fn from(n: $ty) -> Self {
31                    VariableValue::Integer(n.into())
32                }
33            }
34        )*
35    };
36}
37
38from_integer! {
39    i8 i16 i32 i64 isize
40    u8 u16 u32 u64 usize
41}
42
43impl From<f32> for VariableValue {
44    fn from(n: f32) -> Self {
45        Float::from_f32(n).map_or(VariableValue::Null, VariableValue::Float)
46    }
47}
48
49impl From<f64> for VariableValue {
50    fn from(n: f64) -> Self {
51        Float::from_f64(n).map_or(VariableValue::Null, VariableValue::Float)
52    }
53}
54
55impl From<bool> for VariableValue {
56    fn from(b: bool) -> Self {
57        VariableValue::Bool(b)
58    }
59}
60
61impl From<String> for VariableValue {
62    fn from(s: String) -> Self {
63        if let Ok(date) = NaiveDate::parse_from_str(&s, "%F") {
64            // %Y-%m-%d
65            VariableValue::Date(date)
66        } else {
67            VariableValue::String(s)
68        }
69    }
70}
71
72impl<'a> From<&'a str> for VariableValue {
73    fn from(s: &'a str) -> Self {
74        if let Ok(date) = NaiveDate::parse_from_str(s, "%F") {
75            // %Y-%m-%d
76            VariableValue::Date(date)
77        } else {
78            VariableValue::String(s.to_string())
79        }
80    }
81}
82
83impl<'a> From<Cow<'a, str>> for VariableValue {
84    fn from(s: Cow<'a, str>) -> Self {
85        VariableValue::String(s.into_owned())
86    }
87}
88
89impl From<Integer> for VariableValue {
90    fn from(n: Integer) -> Self {
91        VariableValue::Integer(n)
92    }
93}
94
95impl From<Float> for VariableValue {
96    fn from(n: Float) -> Self {
97        VariableValue::Float(n)
98    }
99}
100
101impl From<BTreeMap<String, VariableValue>> for VariableValue {
102    fn from(m: BTreeMap<String, VariableValue>) -> Self {
103        VariableValue::Object(m)
104    }
105}
106
107impl From<Map<String, Value>> for VariableValue {
108    fn from(m: Map<String, Value>) -> Self {
109        VariableValue::Object(m.into_iter().map(|(k, v)| (k, v.into())).collect())
110    }
111}
112
113impl<T: Into<VariableValue>> From<Vec<T>> for VariableValue {
114    fn from(v: Vec<T>) -> Self {
115        VariableValue::List(v.into_iter().map(|e| e.into()).collect())
116    }
117}
118
119impl<'a, T: Clone + Into<VariableValue>> From<&'a [T]> for VariableValue {
120    // Convert a slice to a value
121    fn from(v: &'a [T]) -> Self {
122        VariableValue::List(v.iter().cloned().map(Into::into).collect())
123    }
124}
125
126impl<T: Into<VariableValue>> FromIterator<T> for VariableValue {
127    // Convert an iterable type to a value
128    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
129        VariableValue::List(iter.into_iter().map(Into::into).collect())
130    }
131}
132
133impl<K: Into<String>, V: Into<VariableValue>> FromIterator<(K, V)> for VariableValue {
134    // Convert an iterable type to a value
135    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
136        VariableValue::Object(
137            iter.into_iter()
138                .map(|(k, v)| (k.into(), v.into()))
139                .collect(),
140        )
141    }
142}
143
144impl From<()> for VariableValue {
145    // Convert `()` to a null value
146    fn from((): ()) -> Self {
147        VariableValue::Null
148    }
149}
150
151impl<T> From<Option<T>> for VariableValue
152where
153    T: Into<VariableValue>,
154{
155    fn from(o: Option<T>) -> Self {
156        match o {
157            Some(v) => Into::into(v),
158            None => VariableValue::Null,
159        }
160    }
161}
162
163impl From<ZonedTime> for VariableValue {
164    fn from(date_time: ZonedTime) -> Self {
165        VariableValue::ZonedTime(date_time)
166    }
167}
168
169impl From<ZonedDateTime> for VariableValue {
170    fn from(date_time: ZonedDateTime) -> Self {
171        VariableValue::ZonedDateTime(date_time)
172    }
173}
174
175impl From<NaiveTime> for VariableValue {
176    fn from(time: NaiveTime) -> Self {
177        VariableValue::LocalTime(time)
178    }
179}
180
181impl From<Value> for VariableValue {
182    fn from(value: Value) -> Self {
183        match value {
184            Value::Null => VariableValue::Null,
185            Value::Bool(b) => VariableValue::Bool(b),
186            Value::Number(num) => {
187                if let Some(n) = num.as_i64() {
188                    VariableValue::Integer(n.into())
189                } else {
190                    VariableValue::Float(
191                        Float::from_f64(num.as_f64().unwrap_or(0.0)).expect("valid float"),
192                    )
193                }
194            }
195            Value::String(s) => VariableValue::String(s),
196            Value::Array(arr) => {
197                let variable_values: Vec<VariableValue> =
198                    arr.into_iter().map(VariableValue::from).collect();
199                VariableValue::List(variable_values)
200            }
201            Value::Object(obj) => {
202                let variable_values: BTreeMap<String, VariableValue> = obj
203                    .into_iter()
204                    .map(|(k, v)| (k.to_string(), VariableValue::from(v)))
205                    .collect();
206                VariableValue::Object(variable_values)
207            }
208        }
209    }
210}