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
10pub type TupleType<NumericTypes = DefaultNumericTypes> = Vec<Value<NumericTypes>>;
12
13pub type EmptyType = ();
15
16pub const EMPTY_VALUE: () = ();
18
19#[derive(Clone, Debug, PartialEq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23pub enum Value<NumericTypes: EvalexprNumericTypes = DefaultNumericTypes> {
24 String(String),
26 Float(NumericTypes::Float),
28 Int(NumericTypes::Int),
30 Boolean(bool),
32 Tuple(TupleType<NumericTypes>),
34 Empty,
36}
37
38impl<NumericTypes: EvalexprNumericTypes> Value<NumericTypes> {
39 pub fn is_string(&self) -> bool {
41 matches!(self, Value::String(_))
42 }
43 pub fn is_int(&self) -> bool {
45 matches!(self, Value::Int(_))
46 }
47
48 pub fn is_float(&self) -> bool {
50 matches!(self, Value::Float(_))
51 }
52
53 pub fn is_number(&self) -> bool {
55 matches!(self, Value::Int(_) | Value::Float(_))
56 }
57
58 pub fn is_boolean(&self) -> bool {
60 matches!(self, Value::Boolean(_))
61 }
62
63 pub fn is_tuple(&self) -> bool {
65 matches!(self, Value::Tuple(_))
66 }
67
68 pub fn is_empty(&self) -> bool {
70 matches!(self, Value::Empty)
71 }
72
73 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 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 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 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 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 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 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 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 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 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 pub fn from_float(float: NumericTypes::Float) -> Self {
182 Self::Float(float)
183 }
184
185 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}