fastn_resolved/evalexpr/value/
mod.rs

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