excel_lib/evaluate/
value.rs

1use chrono::{Duration, NaiveDate}; 
2use std::fmt; 
3use std::cmp::{Eq, PartialEq, PartialOrd, Ordering};
4use std::ops::{Add, Sub, Mul, Div, Neg, AddAssign};  
5use ndarray::Array2; 
6
7use crate::reference::Reference;
8use crate::parser::ast::Error; 
9
10type NumType = f64;
11type BoolType = bool;
12type TextType = String; 
13type ArrayType = Vec<Value>;
14type Array2Type = Array2<Value>;
15type DateType = NaiveDate; 
16type ErrorType = Error; 
17
18#[derive(Clone, PartialEq, Debug)]
19pub enum Value { 
20    Num(NumType), 
21    Bool(BoolType), 
22    Text(TextType), 
23    Date(DateType), 
24    Array(ArrayType), 
25    Array2(Array2Type), 
26    Formula(TextType), 
27    Error(ErrorType), 
28    Range { sheet: Option<String>, reference: Reference, value: Option<Box<Value>> }, 
29    Empty
30}
31
32impl From<f64> for Value { fn from(f: NumType) -> Value { Value::Num(f) }}
33impl From<i32> for Value { fn from(f: i32) -> Value { Value::Num(f as f64) }}
34impl From<usize> for Value { fn from(f: usize) -> Value { Value::Num(f as f64) }}
35impl From<bool> for Value { fn from(b: BoolType) -> Value { Value::Bool(b) }}
36impl From<String> for Value { fn from(s: TextType) -> Value { Value::Text(s) }}
37impl From<&str> for Value { fn from(s: &str) -> Value { Value::Text(s.to_string()) }}
38impl From<Vec<Value>> for Value { fn from(v: ArrayType) -> Value { Value::Array(v) }}
39impl From<Array2<Value>> for Value { fn from(v: Array2Type) -> Value { Value::Array2(v) }}
40impl From<NaiveDate> for Value { fn from(d: DateType) -> Value { Value::Date(d) }}
41
42impl Value {
43    pub fn is_num(&self) -> bool { matches!(self, Value::Num(_)) }
44    pub fn is_bool(&self) -> bool { matches!(self, Value::Bool(_)) }
45    pub fn is_text(&self) -> bool { matches!(self, Value::Text(_)) }
46    pub fn is_date(&self) -> bool { matches!(self, Value::Date(_)) }
47    pub fn is_array(&self) -> bool { matches!(self, Value::Array(_)) }
48    pub fn is_array2(&self) -> bool { matches!(self, Value::Array2(_)) }
49    pub fn is_empty(&self) -> bool { matches!(self, Value::Empty) }
50    pub fn is_formula(&self) -> bool { matches!(self, Value::Formula(_)) }
51    pub fn is_range(&self) -> bool { matches!(self, Value::Range {sheet: _, reference: _, value: _}) }
52    pub fn is_err(&self) -> bool { matches!(self, Value::Error(_)) }
53
54    pub fn ensure_single(&self) -> Value {
55        match self {
56            Value::Array2(arr2) => arr2[[0,0]].ensure_single().clone(), // assume single
57            Value::Array(arr) => arr.get(0).unwrap().ensure_single().clone(), // assume single
58            c => c.clone() // TODO
59        }
60    }
61
62    pub fn as_num(&self) -> NumType {
63        match self {
64            Value::Num(x) => {
65                if x.is_nan() {
66                    0.0 
67                } else {
68                    *x
69                }
70            },
71            Value::Text(t) => t.parse::<NumType>().unwrap(), 
72            Value::Bool(x) => {
73                match x {
74                    true => 1.0, 
75                    false => 0.0
76                }
77            }, 
78            Value::Array2(arr2) => { // Assume single cell
79                arr2[[0,0]].as_num()
80            }, 
81            Value::Empty => 0.0, 
82            _ => panic!("{} cannot be converted to a number.", self)
83        }
84    }
85
86    pub fn as_bool(&self) -> BoolType {
87        match self {
88            Value::Bool(x) => *x, 
89            Value::Num(n) => {
90                if *n == 1.0 {
91                    true
92                } else if *n == 0.0 {
93                    false
94                } else {
95                    panic!("{} cannot be converted to a boolean.", self)
96                }
97            }, 
98            _ => panic!("{} cannot be converted to a boolean.", self)
99        }
100    }
101
102    pub fn as_text(&self) -> TextType {
103        match self {
104            Value::Text(x) 
105                | Value::Formula(x) => x.clone(), 
106            Value::Array2(arr2) => { // Assume single cell
107                arr2[[0,0]].as_text()
108            }, 
109            c => format!("{}", c)
110        } 
111    }
112
113    pub fn as_date(&self) -> DateType {
114        match self { 
115            Value::Date(x) => *x,
116            Value::Array2(arr2) => {
117                arr2[[0,0]].as_date()
118            }, 
119            _ => panic!("{} cannot be converted to a date.", self)
120        }
121    }
122
123    pub fn as_array(&self) -> ArrayType {
124        match self {
125            Value::Array(arr) => arr.to_vec(),
126            Value::Array2(arr2) => arr2.clone().into_raw_vec(), 
127            c => vec![c.clone()], 
128        }
129    }
130
131    pub fn as_array2(&self) -> Array2Type {
132        match self {
133            Value::Array2(arr2) => arr2.clone(), 
134            _ => panic!("{} cannot be converted to an array2.", self)
135        }
136    }
137
138    pub fn as_err(&self) -> ErrorType {
139        if let Value::Error(err) = self {
140            err.clone()
141        } else {
142            panic!("{} cannot be converted to an error.", self)
143        }
144    }
145}
146
147impl fmt::Display for Value {
148    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
149        match self {
150            Value::Num(x) => { 
151                if x.is_nan() {
152                    write!(f, "{}", "0") 
153                } else {
154                    write!(f, "{}", x) 
155                } 
156            }, 
157            Value::Bool(x) => { write!(f, "{}", if *x { "TRUE" } else { "FALSE" }) }, 
158            Value::Text(x) => { write!(f, "\"{}\"", x) },
159            Value::Formula(x) => { write!(f, "{}", x) }, 
160            Value::Date(x) => { write!(f, "{}", x) }, 
161            Value::Array(x) => {
162                x.iter().fold(Ok(()), |result, output| {
163                    result.and_then(|_| writeln!(f, "{}", output)) 
164                })
165            }, 
166            Value::Empty => { write!(f, "\"\"") }
167            Value::Range {sheet, reference, value: _} => { 
168                match sheet {
169                    Some(s) => write!(f, "{}!{}", s, reference), 
170                    None => write!(f, "{}", reference)
171                }
172            }, 
173            Value::Array2(arr2) => write!(f, "{}", arr2), 
174            Value::Error(err) => write!(f, "{}", err)
175        }
176    }
177}
178
179impl Eq for Value { }
180
181fn variant_ord(v : &Value) -> usize {
182    let variants : Vec<bool> = vec![
183        v.is_bool(),
184        v.is_text(),
185        v.is_num(),
186        v.is_date()
187    ];
188    let variant_len : usize = variants.len();
189    match variants.into_iter().position(|x| x) {
190        Some(u) => {
191            u
192        },
193        None => {
194            variant_len
195        }
196    }
197}
198
199impl PartialOrd for Value {
200    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
201        let self_rank : usize = variant_ord(self);
202        let other_rank : usize = variant_ord(other);
203        match self_rank.cmp(&other_rank) {
204            Ordering::Greater => {
205                Some(Ordering::Greater)
206            },
207            Ordering::Less => {
208                Some(Ordering::Less)
209            },
210            Ordering::Equal => {
211                if self.is_bool() {
212                    Some(self.as_bool().cmp(&other.as_bool()))
213                } else if self.is_text() {
214                    Some(self.as_text().cmp(&other.as_text()))
215                } else if self.is_num() {
216                    let a = self.as_num();
217                    let b = other.as_num();
218                    if a > b {
219                        Some(Ordering::Greater)
220                    } else if a < b {
221                        Some(Ordering::Less)
222                    } else {
223                        Some(Ordering::Equal)
224                    }
225                } else if self.is_date() {
226                    Some(self.as_date().cmp(&other.as_date()))
227                } else {
228                    None
229                }
230            }
231        }
232    }
233}
234
235impl Ord for Value {
236    fn cmp(&self, other: &Self) -> Ordering {
237        self.partial_cmp(other).unwrap()
238    }
239}
240
241impl Add for Value {
242    type Output = Self; 
243    fn add(self, other: Self) -> Self {
244        match self.ensure_single() {
245            Value::Num(x) => Value::from(x + other.ensure_single().as_num()), 
246            Value::Text(ref x) => Value::from(format!("{}{}", x, other.ensure_single().as_text())),
247            Value::Bool(_) => Value::from(self.as_num() + other.ensure_single().as_num()), 
248            Value::Empty => Value::from(0.0 + other.ensure_single().as_num()), 
249            Value::Date(dt) => {
250                Value::from(dt.checked_add_signed(Duration::days(other.ensure_single().as_num() as i64)).unwrap())
251            }, 
252            Value::Error(_) => self, 
253            _ => panic!("{} cannot be added to {}.", other, self)
254        }
255    }
256}
257
258impl AddAssign for Value {
259    fn add_assign(&mut self, other: Self) {
260        if self.ensure_single().is_num() {
261            *self = self.ensure_single() + other
262        } else {
263            panic!("{} cannot be add assigned to {}.", other, self)
264        }
265    }
266}
267
268impl Sub for Value {
269    type Output = Self; 
270    fn sub(self, other: Self) -> Self {
271        match self.ensure_single() {
272            Value::Num(x) => Value::from(x - other.ensure_single().as_num()), 
273            Value::Bool(_) => Value::from(self.as_num() - other.ensure_single().as_num()), 
274            Value::Empty => Value::from(0.0 - other.ensure_single().as_num()), 
275            Value::Date(dt) => {
276                let other_single = other.ensure_single(); 
277                if other_single.is_date() {
278                        Value::from(NaiveDate::signed_duration_since(dt, other_single.as_date()).num_days() as f64)
279                } else {
280                    Value::from(dt.checked_sub_signed(Duration::days(other_single.as_num() as i64)).unwrap())
281                }
282            }, 
283            Value::Error(_) => self, 
284            _ => panic!("{} cannot be subtracted from {}.", other, self)
285        }
286    }
287}
288
289impl Mul for Value {
290    type Output = Self; 
291    fn mul(self, other: Self) -> Self {
292        match self.ensure_single() {
293            Value::Num(x) => Value::from(x * other.ensure_single().as_num()), 
294            Value::Bool(_) => Value::from(self.as_num() * other.ensure_single().as_num()), 
295            Value::Empty => Value::from(0.0 * other.ensure_single().as_num()), 
296            Value::Error(_) => self, 
297            // TODO
298            _ => panic!("{} cannot be multiplied by {}.", self, other)
299        }
300    }
301}
302
303impl Div for Value {
304    type Output = Self; 
305    fn div(self, other: Self) -> Self {
306        match self.ensure_single() {
307            Value::Num(x) => Value::from(x / other.ensure_single().as_num()), 
308            Value::Error(_) => self, 
309            // TODO
310            _ => panic!("{} cannot be divided by {}.", self, other)
311        }
312    }
313}
314
315impl Neg for Value {
316    type Output = Self;
317    fn neg(self) -> Self {
318        match self {
319            Value::Error(_) => self, 
320            _ => Value::from(-self.as_num()),
321        }
322    }
323}