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(), Value::Array(arr) => arr.get(0).unwrap().ensure_single().clone(), c => c.clone() }
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) => { 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) => { 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 _ => 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 _ => 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}