evalexpr/value/
mod.rs

1use crate::error::{EvalexprError, EvalexprResult, EvalexprResultValue};
2use std::{convert::TryFrom, ops::RangeInclusive};
3
4use self::numeric_types::{default_numeric_types::DefaultNumericTypes, EvalexprNumericTypes};
5
6mod display;
7pub mod numeric_types;
8pub mod value_type;
9
10/// The type used to represent tuples in `Value::Tuple`.
11pub type TupleType<NumericTypes = DefaultNumericTypes> = Vec<Value<NumericTypes>>;
12
13/// The type used to represent empty values in `Value::Empty`.
14pub type EmptyType = ();
15
16/// The value of the empty type to be used in rust.
17pub const EMPTY_VALUE: () = ();
18
19/// The value type used by the parser.
20/// Values can be of different subtypes that are the variants of this enum.
21#[derive(Clone, Debug, PartialEq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub enum Value<NumericTypes: EvalexprNumericTypes = DefaultNumericTypes> {
24    /// A string value.
25    String(String),
26    /// A float value.
27    Float(NumericTypes::Float),
28    /// An integer value.
29    Int(NumericTypes::Int),
30    /// A boolean value.
31    Boolean(bool),
32    /// A tuple value.
33    Tuple(TupleType<NumericTypes>),
34    /// An empty value.
35    Empty,
36}
37
38impl<NumericTypes: EvalexprNumericTypes> Value<NumericTypes> {
39    /// Returns true if `self` is a `Value::String`.
40    pub fn is_string(&self) -> bool {
41        matches!(self, Value::String(_))
42    }
43    /// Returns true if `self` is a `Value::Int`.
44    pub fn is_int(&self) -> bool {
45        matches!(self, Value::Int(_))
46    }
47
48    /// Returns true if `self` is a `Value::Float`.
49    pub fn is_float(&self) -> bool {
50        matches!(self, Value::Float(_))
51    }
52
53    /// Returns true if `self` is a `Value::Int` or `Value::Float`.
54    pub fn is_number(&self) -> bool {
55        matches!(self, Value::Int(_) | Value::Float(_))
56    }
57
58    /// Returns true if `self` is a `Value::Boolean`.
59    pub fn is_boolean(&self) -> bool {
60        matches!(self, Value::Boolean(_))
61    }
62
63    /// Returns true if `self` is a `Value::Tuple`.
64    pub fn is_tuple(&self) -> bool {
65        matches!(self, Value::Tuple(_))
66    }
67
68    /// Returns true if `self` is a `Value::Empty`.
69    pub fn is_empty(&self) -> bool {
70        matches!(self, Value::Empty)
71    }
72
73    /// Clones the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::String`.
74    pub fn as_string(&self) -> EvalexprResult<String, NumericTypes> {
75        match self {
76            Value::String(string) => Ok(string.clone()),
77            value => Err(EvalexprError::expected_string(value.clone())),
78        }
79    }
80
81    /// Clones the value stored in `self` as `IntType`, or returns `Err` if `self` is not a `Value::Int`.
82    pub fn as_int(&self) -> EvalexprResult<NumericTypes::Int, NumericTypes> {
83        match self {
84            Value::Int(i) => Ok(i.clone()),
85            value => Err(EvalexprError::expected_int(value.clone())),
86        }
87    }
88
89    /// Clones the value stored in  `self` as `FloatType`, or returns `Err` if `self` is not a `Value::Float`.
90    pub fn as_float(&self) -> EvalexprResult<NumericTypes::Float, NumericTypes> {
91        match self {
92            Value::Float(f) => Ok(f.clone()),
93            value => Err(EvalexprError::expected_float(value.clone())),
94        }
95    }
96
97    /// Clones the value stored in  `self` as `FloatType`, or returns `Err` if `self` is not a `Value::Float` or `Value::Int`.
98    /// Note that this method silently converts `IntType` to `FloatType`, if `self` is a `Value::Int`.
99    pub fn as_number(&self) -> EvalexprResult<NumericTypes::Float, NumericTypes> {
100        match self {
101            Value::Float(f) => Ok(f.clone()),
102            Value::Int(i) => Ok(NumericTypes::int_as_float(i)),
103            value => Err(EvalexprError::expected_number(value.clone())),
104        }
105    }
106
107    /// Clones the value stored in  `self` as `bool`, or returns `Err` if `self` is not a `Value::Boolean`.
108    pub fn as_boolean(&self) -> EvalexprResult<bool, NumericTypes> {
109        match self {
110            Value::Boolean(boolean) => Ok(*boolean),
111            value => Err(EvalexprError::expected_boolean(value.clone())),
112        }
113    }
114
115    /// Clones the value stored in `self` as `TupleType`, or returns `Err` if `self` is not a `Value::Tuple`.
116    pub fn as_tuple(&self) -> EvalexprResult<TupleType<NumericTypes>, NumericTypes> {
117        match self {
118            Value::Tuple(tuple) => Ok(tuple.clone()),
119            value => Err(EvalexprError::expected_tuple(value.clone())),
120        }
121    }
122
123    /// Clones the value stored in `self` as `TupleType` or returns `Err` if `self` is not a `Value::Tuple` of the required length.
124    pub fn as_fixed_len_tuple(
125        &self,
126        len: usize,
127    ) -> EvalexprResult<TupleType<NumericTypes>, NumericTypes> {
128        match self {
129            Value::Tuple(tuple) => {
130                if tuple.len() == len {
131                    Ok(tuple.clone())
132                } else {
133                    Err(EvalexprError::expected_fixed_len_tuple(len, self.clone()))
134                }
135            },
136            value => Err(EvalexprError::expected_tuple(value.clone())),
137        }
138    }
139
140    /// Clones the value stored in `self` as `TupleType` or returns `Err` if `self` is not a `Value::Tuple` with length in the required range.
141    pub fn as_ranged_len_tuple(
142        &self,
143        range: RangeInclusive<usize>,
144    ) -> EvalexprResult<TupleType<NumericTypes>, NumericTypes> {
145        match self {
146            Value::Tuple(tuple) => {
147                if range.contains(&tuple.len()) {
148                    Ok(tuple.clone())
149                } else {
150                    Err(EvalexprError::expected_ranged_len_tuple(
151                        range,
152                        self.clone(),
153                    ))
154                }
155            },
156            value => Err(EvalexprError::expected_tuple(value.clone())),
157        }
158    }
159
160    /// Returns `()`, or returns`Err` if `self` is not a `Value::Tuple`.
161    pub fn as_empty(&self) -> EvalexprResult<(), NumericTypes> {
162        match self {
163            Value::Empty => Ok(()),
164            value => Err(EvalexprError::expected_empty(value.clone())),
165        }
166    }
167
168    /// Returns a string for the `str::from` built-in function.
169    pub fn str_from(&self) -> String {
170        match self {
171            Value::String(v) => v.to_string(),
172            Value::Float(v) => v.to_string(),
173            Value::Int(v) => v.to_string(),
174            Value::Boolean(v) => v.to_string(),
175            Value::Tuple(_) => self.to_string(),
176            Value::Empty => String::from("()"),
177        }
178    }
179
180    /// Create a new `Value` from its corresponding raw float type.
181    pub fn from_float(float: NumericTypes::Float) -> Self {
182        Self::Float(float)
183    }
184
185    /// Create a new `Value` from its corresponding raw int type.
186    pub fn from_int(int: NumericTypes::Int) -> Self {
187        Self::Int(int)
188    }
189}
190
191impl<NumericTypes: EvalexprNumericTypes> From<String> for Value<NumericTypes> {
192    fn from(string: String) -> Self {
193        Value::String(string)
194    }
195}
196
197impl<NumericTypes: EvalexprNumericTypes> From<&str> for Value<NumericTypes> {
198    fn from(string: &str) -> Self {
199        Value::String(string.to_string())
200    }
201}
202
203impl<NumericTypes: EvalexprNumericTypes> From<bool> for Value<NumericTypes> {
204    fn from(boolean: bool) -> Self {
205        Value::Boolean(boolean)
206    }
207}
208
209impl<NumericTypes: EvalexprNumericTypes> From<TupleType<NumericTypes>> for Value<NumericTypes> {
210    fn from(tuple: TupleType<NumericTypes>) -> Self {
211        Value::Tuple(tuple)
212    }
213}
214
215impl<NumericTypes: EvalexprNumericTypes> From<Value<NumericTypes>>
216    for EvalexprResultValue<NumericTypes>
217{
218    fn from(value: Value<NumericTypes>) -> Self {
219        Ok(value)
220    }
221}
222
223impl<NumericTypes: EvalexprNumericTypes> From<()> for Value<NumericTypes> {
224    fn from(_: ()) -> Self {
225        Value::Empty
226    }
227}
228
229impl<NumericTypes: EvalexprNumericTypes> TryFrom<Value<NumericTypes>> for String {
230    type Error = EvalexprError<NumericTypes>;
231
232    fn try_from(value: Value<NumericTypes>) -> Result<Self, Self::Error> {
233        if let Value::String(value) = value {
234            Ok(value)
235        } else {
236            Err(EvalexprError::ExpectedString { actual: value })
237        }
238    }
239}
240
241impl<NumericTypes: EvalexprNumericTypes> TryFrom<Value<NumericTypes>> for bool {
242    type Error = EvalexprError<NumericTypes>;
243
244    fn try_from(value: Value<NumericTypes>) -> Result<Self, Self::Error> {
245        if let Value::Boolean(value) = value {
246            Ok(value)
247        } else {
248            Err(EvalexprError::ExpectedBoolean { actual: value })
249        }
250    }
251}
252
253impl<NumericTypes: EvalexprNumericTypes> TryFrom<Value<NumericTypes>> for TupleType<NumericTypes> {
254    type Error = EvalexprError<NumericTypes>;
255
256    fn try_from(value: Value<NumericTypes>) -> Result<Self, Self::Error> {
257        if let Value::Tuple(value) = value {
258            Ok(value)
259        } else {
260            Err(EvalexprError::ExpectedTuple { actual: value })
261        }
262    }
263}
264
265impl<NumericTypes: EvalexprNumericTypes> TryFrom<Value<NumericTypes>> for () {
266    type Error = EvalexprError<NumericTypes>;
267
268    fn try_from(value: Value<NumericTypes>) -> Result<Self, Self::Error> {
269        if let Value::Empty = value {
270            Ok(())
271        } else {
272            Err(EvalexprError::ExpectedEmpty { actual: value })
273        }
274    }
275}
276
277#[cfg(test)]
278mod tests {
279    use crate::value::{
280        numeric_types::default_numeric_types::DefaultNumericTypes, TupleType, Value,
281    };
282
283    #[test]
284    fn test_value_conversions() {
285        assert_eq!(
286            Value::<DefaultNumericTypes>::from("string").as_string(),
287            Ok(String::from("string"))
288        );
289        assert_eq!(Value::<DefaultNumericTypes>::from_int(3).as_int(), Ok(3));
290        assert_eq!(
291            Value::<DefaultNumericTypes>::from_float(3.3).as_float(),
292            Ok(3.3)
293        );
294        assert_eq!(
295            Value::<DefaultNumericTypes>::from(true).as_boolean(),
296            Ok(true)
297        );
298        assert_eq!(
299            Value::<DefaultNumericTypes>::from(TupleType::new()).as_tuple(),
300            Ok(TupleType::new())
301        );
302    }
303
304    #[test]
305    fn test_value_checks() {
306        assert!(Value::<DefaultNumericTypes>::from("string").is_string());
307        assert!(Value::<DefaultNumericTypes>::from_int(3).is_int());
308        assert!(Value::<DefaultNumericTypes>::from_float(3.3).is_float());
309        assert!(Value::<DefaultNumericTypes>::from(true).is_boolean());
310        assert!(Value::<DefaultNumericTypes>::from(TupleType::new()).is_tuple());
311    }
312
313    #[test]
314    fn test_value_str_from() {
315        assert_eq!(
316            Value::<DefaultNumericTypes>::from("string").str_from(),
317            "string"
318        );
319        assert_eq!(
320            Value::<DefaultNumericTypes>::from_float(3.3).str_from(),
321            "3.3"
322        );
323        assert_eq!(Value::<DefaultNumericTypes>::from_int(3).str_from(), "3");
324        assert_eq!(Value::<DefaultNumericTypes>::from(true).str_from(), "true");
325        assert_eq!(Value::<DefaultNumericTypes>::from(()).str_from(), "()");
326        assert_eq!(
327            Value::<DefaultNumericTypes>::from(TupleType::from([
328                Value::<DefaultNumericTypes>::from("string"),
329                Value::<DefaultNumericTypes>::from_float(3.3),
330                Value::<DefaultNumericTypes>::from_int(3),
331                Value::<DefaultNumericTypes>::from(TupleType::from([
332                    Value::<DefaultNumericTypes>::from_int(42),
333                    Value::<DefaultNumericTypes>::from_float(4.2),
334                ])),
335                Value::<DefaultNumericTypes>::from(()),
336                Value::<DefaultNumericTypes>::from(true),
337            ]))
338            .str_from(),
339            r#"("string", 3.3, 3, (42, 4.2), (), true)"#
340        );
341    }
342}