1use crate::operator::expr::{Expr, ValueRef};
2use crate::operator::EvalError;
3use chrono::{DateTime, Duration, Utc};
4use itertools::Itertools;
5use ordered_float::OrderedFloat;
6use serde::ser::{SerializeMap, SerializeSeq};
7use serde::Serializer;
8use std::cmp::Ordering;
9use std::collections::HashMap;
10use std::convert::{TryFrom, TryInto};
11use std::fmt;
12use std::fmt::{Display, Formatter};
13use std::ops::{Add, Div, Mul, Sub};
14
15pub type VMap = HashMap<String, Value>;
16
17pub enum Row {
18 Aggregate(Aggregate),
19 Record(Record),
20}
21
22pub(crate) struct WrappedAggregateRow<'a> {
27 pub columns: &'a Vec<String>,
28 pub data: &'a VMap,
29}
30
31impl serde::Serialize for WrappedAggregateRow<'_> {
32 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
33 where
34 S: Serializer,
35 {
36 let mut map = serializer.serialize_map(Some(self.columns.len()))?;
37 for k in self.columns {
38 map.serialize_entry(k, self.data.get(k).unwrap_or(&Value::None))?;
39 }
40 map.end()
41 }
42}
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub struct Aggregate {
46 pub columns: Vec<String>,
47 pub data: Vec<VMap>,
48}
49
50impl serde::Serialize for Aggregate {
55 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
56 where
57 S: Serializer,
58 {
59 let mut seq = serializer.serialize_seq(Some(self.data.len()))?;
60 for row in &self.data {
61 seq.serialize_element(&WrappedAggregateRow {
62 columns: &self.columns,
63 data: row,
64 })?
65 }
66 seq.end()
67 }
68}
69
70#[derive(Debug, PartialEq, Eq, Clone)]
71pub struct Record {
72 pub data: VMap,
73 pub raw: String,
74}
75
76impl serde::Serialize for Record {
77 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
78 where
79 S: Serializer,
80 {
81 let mut map = serializer.serialize_map(Some(self.data.len()))?;
82 for (k, v) in self.data.iter().sorted() {
83 map.serialize_entry(k, v)?;
84 }
85 map.end()
86 }
87}
88
89#[derive(Clone, Debug, PartialEq, Eq, Hash)]
90pub enum Value {
91 Str(String),
92 Int(i64),
94 Float(OrderedFloat<f64>),
95 Bool(bool),
96 DateTime(DateTime<Utc>),
97 Duration(Duration),
98 Obj(im::HashMap<String, Value>),
99 Array(Vec<Value>),
100 None,
101}
102
103impl serde::Serialize for Value {
104 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
105 where
106 S: Serializer,
107 {
108 match self {
109 Value::Str(s) => serializer.serialize_str(s),
110 Value::Int(i) => serializer.serialize_i64(*i),
111 Value::Float(ofloat) => serializer.serialize_f64(ofloat.0),
112 Value::Bool(b) => serializer.serialize_bool(*b),
113 Value::DateTime(dt) => serializer.serialize_str(dt.to_rfc3339().as_str()),
114 Value::Duration(d) => serializer.serialize_str(d.to_string().as_str()),
115 Value::Obj(map) => {
116 let mut m = serializer.serialize_map(Some(map.len()))?;
117 for (k, v) in map {
118 m.serialize_entry(k, v)?;
119 }
120 m.end()
121 }
122 Value::Array(v) => serializer.collect_seq(v),
123 Value::None => serializer.serialize_none(),
124 }
125 }
126}
127
128impl Ord for Value {
129 fn cmp(&self, other: &Self) -> Ordering {
130 match (self, other) {
131 (Value::Int(int_val), Value::Float(float_val)) => {
133 (OrderedFloat::from(*int_val as f64)).cmp(float_val)
134 }
135 (Value::Float(float_val), Value::Int(int_val)) => {
136 float_val.cmp(&OrderedFloat::from(*int_val as f64))
137 }
138 (Value::Float(l), Value::Float(r)) => l.cmp(r),
139 (Value::Int(l), Value::Int(r)) => l.cmp(r),
140 (Value::Str(l), Value::Str(r)) => l.cmp(r),
141 (Value::Bool(l), Value::Bool(r)) => l.cmp(r),
142 (Value::DateTime(l), Value::DateTime(r)) => l.cmp(r),
143 (Value::Duration(l), Value::Duration(r)) => l.cmp(r),
144 (Value::Obj(l), Value::Obj(r)) => l.cmp(r),
145 (unrelated_l, unrelated_r) => unrelated_l.rank().cmp(&unrelated_r.rank()),
147 }
148 }
149}
150
151impl PartialOrd for Value {
152 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
153 Some(self.cmp(other))
154 }
155}
156
157impl Display for Value {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 match *self {
160 Value::Str(ref s) => write!(f, "{}", s),
161 Value::Int(ref s) => write!(f, "{}", s),
162 Value::Float(ref s) => write!(f, "{}", s),
163 Value::Bool(ref s) => write!(f, "{}", s),
164 Value::DateTime(ref dt) => write!(f, "{:?}", dt),
165 Value::Duration(ref d) => write!(f, "{:?}", d),
166 Value::Obj(ref o) => write!(f, "{:?}", o),
167 Value::Array(ref o) => write!(f, "{:?}", o),
168 Value::None => write!(f, "None"),
169 }
170 }
171}
172
173impl Add for Value {
174 type Output = Result<Value, EvalError>;
175
176 fn add(self, rhs: Self) -> Self::Output {
177 match (self, rhs) {
178 (Value::DateTime(ldt), Value::Duration(rd)) => Ok(Value::DateTime(ldt.add(rd))),
179 (Value::Duration(ld), Value::DateTime(rdt)) => Ok(Value::DateTime(rdt.add(ld))),
180 (Value::Duration(ld), Value::Duration(rd)) => Ok(Value::Duration(ld.add(rd))),
181 (Value::Float(lf), Value::Float(rf)) => Ok(Value::Float(lf + rf)),
182 (Value::Int(li), Value::Int(ri)) => Ok(Value::Int(li + ri)),
183 (left, right) => left.binary_op(&f64::add, "+", &right),
184 }
185 }
186}
187
188impl Sub for Value {
189 type Output = Result<Value, EvalError>;
190
191 fn sub(self, rhs: Self) -> Self::Output {
192 match (self, rhs) {
193 (Value::DateTime(ldt), Value::Duration(rf)) => Ok(Value::DateTime(ldt.sub(rf))),
194 (Value::DateTime(ldt), Value::DateTime(rdt)) => Ok(Value::Duration(ldt.sub(rdt))),
195 (Value::Duration(ld), Value::Duration(rd)) => Ok(Value::Duration(ld.sub(rd))),
196 (Value::Float(lf), Value::Float(rf)) => Ok(Value::Float(lf - rf)),
197 (Value::Int(li), Value::Int(ri)) => Ok(Value::Int(li - ri)),
198 (left, right) => left.binary_op(&f64::sub, "-", &right),
199 }
200 }
201}
202
203impl Mul for Value {
204 type Output = Result<Value, EvalError>;
205
206 fn mul(self, rhs: Self) -> Self::Output {
207 match (self, rhs) {
208 (Value::Duration(ld), Value::Int(ri)) => Ok(Value::Duration(ld.mul(ri as i32))),
209 (Value::Int(li), Value::Duration(rd)) => Ok(Value::Duration(rd.mul(li as i32))),
210 (Value::Float(lf), Value::Float(rf)) => Ok(Value::Float(lf * rf)),
211 (Value::Int(li), Value::Int(ri)) => Ok(Value::Int(li * ri)),
212 (left, right) => left.binary_op(&f64::mul, "*", &right),
213 }
214 }
215}
216
217impl Div for Value {
218 type Output = Result<Value, EvalError>;
219
220 fn div(self, rhs: Self) -> Self::Output {
221 match (self, rhs) {
222 (Value::Duration(ld), Value::Int(ri)) => Ok(Value::Duration(ld.div(ri as i32))),
223 (left, right) => left.binary_op(&f64::div, "/", &right),
224 }
225 }
226}
227
228#[derive(Clone)]
229pub struct DisplayConfig {
230 pub floating_points: usize,
231}
232
233impl Default for DisplayConfig {
234 fn default() -> Self {
235 DisplayConfig { floating_points: 2 }
236 }
237}
238
239pub(crate) struct ValueDisplay<'a> {
240 value: &'a Value,
241 display_config: &'a DisplayConfig,
242}
243
244impl<'a> ValueDisplay<'a> {
245 pub(crate) fn new(value: &'a Value, display_config: &'a DisplayConfig) -> Self {
246 Self {
247 value,
248 display_config,
249 }
250 }
251
252 fn nested(&self, new_value: &'a Value) -> ValueDisplay<'a> {
253 ValueDisplay {
254 value: new_value,
255 display_config: self.display_config,
256 }
257 }
258}
259
260impl Display for ValueDisplay<'_> {
261 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
262 match *self.value {
263 Value::Str(ref s) => write!(f, "{}", s),
264 Value::Int(ref s) => write!(f, "{}", s),
265 Value::None => write!(f, "None"),
266 Value::Float(ref s) => write!(f, "{:.*}", self.display_config.floating_points, s),
267 Value::Bool(ref s) => write!(f, "{}", s),
268 Value::DateTime(ref dt) => write!(f, "{}", dt),
269 Value::Duration(ref d) => {
270 let mut remaining: Duration = *d;
271 let weeks = remaining.num_seconds() / Duration::weeks(1).num_seconds();
272 remaining = remaining - Duration::weeks(weeks);
273 let days = remaining.num_seconds() / Duration::days(1).num_seconds();
274 remaining = remaining - Duration::days(days);
275 let hours = remaining.num_seconds() / Duration::hours(1).num_seconds();
276 remaining = remaining - Duration::hours(hours);
277 let mins = remaining.num_seconds() / Duration::minutes(1).num_seconds();
278 remaining = remaining - Duration::minutes(mins);
279 let secs = remaining.num_seconds() / Duration::seconds(1).num_seconds();
280 remaining = remaining - Duration::seconds(secs);
281 let msecs = remaining.num_milliseconds();
282 remaining = remaining - Duration::milliseconds(msecs);
283 let usecs = remaining.num_microseconds().unwrap_or(0);
284
285 let pairs = &[
286 (weeks, "w"),
287 (days, "d"),
288 (hours, "h"),
289 (mins, "m"),
290 (secs, "s"),
291 (msecs, "ms"),
292 (usecs, "us"),
293 ];
294
295 for (val, sym) in pairs.iter().filter(|(val, _sym)| *val != 0) {
296 write!(f, "{}{}", val, sym)?;
297 }
298 Ok(())
299 }
300 Value::Obj(ref o) => {
301 let mut items = o.iter().collect::<Vec<_>>();
304 items.sort();
305
306 let mut rendered = items
307 .iter()
308 .map(|(k, v)| format!("{}:{}", k, self.nested(v)));
309 write!(f, "{{{}}}", rendered.join(", "))
310 }
311 Value::Array(ref o) => {
312 let rendered: Vec<_> = o.iter().map(|v| format!("{}", self.nested(v))).collect();
313 write!(f, "[{}]", rendered.join(", "))
314 }
315 }
316 }
317}
318
319impl Value {
320 pub fn rank(&self) -> u8 {
322 match self {
323 Value::None => 0,
324 Value::Bool(_) => 1,
325 Value::Int(_) => 2,
326 Value::Float(_) => 2,
327 Value::Str(_) => 3,
328 Value::DateTime(_) => 4,
329 Value::Duration(_) => 5,
330 Value::Array(_) => 6,
331 Value::Obj(_) => 7,
332 }
333 }
334
335 pub fn render(&self, render_config: &DisplayConfig) -> String {
336 ValueDisplay::new(self, render_config).to_string()
337 }
338
339 pub fn from_bool(b: bool) -> Value {
340 Value::Bool(b)
341 }
342
343 pub fn from_float(f: f64) -> Value {
344 let rounded = f as i64;
345 if (f - f.floor()).abs() < f64::EPSILON {
346 Value::Int(rounded)
347 } else {
348 Value::Float(OrderedFloat(f))
349 }
350 }
351
352 pub fn aggressively_to_num(s: impl AsRef<str> + Into<String>) -> Result<f64, EvalError> {
353 match Value::from_string(
356 s.as_ref()
357 .chars()
358 .filter(|c| c.is_numeric() || c == &'.')
359 .collect::<String>(),
360 ) {
361 Value::Float(f) => Ok(f.0),
362 Value::Int(i) => Ok(i as f64),
363 _other => {
364 Err(EvalError::ExpectedNumber { found: s.into() })
366 }
367 }
368 }
369
370 pub fn from_string(s: impl AsRef<str> + Into<String>) -> Value {
371 let trimmed = s.as_ref().trim();
372 let int_value = trimmed.parse::<i64>();
373 let float_value = trimmed.parse::<f64>();
374 let bool_value = trimmed.parse::<bool>();
375 int_value
376 .map(Value::Int)
377 .or_else(|_| float_value.map(Value::from_float))
378 .or_else(|_| bool_value.map(Value::Bool))
379 .unwrap_or_else(|_| Value::Str(trimmed.into()))
380 }
381
382 pub fn binary_op(
383 &self,
384 op_fn: &dyn Fn(f64, f64) -> f64,
385 op: &'static str,
386 right: &Value,
387 ) -> Result<Value, EvalError> {
388 let left_res: Result<f64, EvalError> = self.try_into();
389 let right_res: Result<f64, EvalError> = right.try_into();
390
391 match (left_res, right_res) {
392 (Ok(lf1), Ok(rf1)) => Ok(Value::from_float(op_fn(lf1, rf1))),
393 _ => Err(EvalError::ExpectedNumericOperands {
394 left: format!("{}", self),
395 op,
396 right: format!("{}", right),
397 }),
398 }
399 }
400}
401
402impl From<f64> for Value {
403 fn from(f: f64) -> Self {
404 Value::from_float(f)
405 }
406}
407
408impl TryFrom<&Value> for f64 {
409 type Error = EvalError;
410
411 fn try_from(value: &Value) -> Result<Self, Self::Error> {
412 match value {
413 Value::Int(i) => Ok(*i as f64),
414 Value::Float(f) => Ok(f.0),
415 Value::Str(s) => Value::aggressively_to_num(s),
416 Value::DateTime(dt) => Ok(dt.timestamp_millis() as f64),
417 _ => Err(EvalError::ExpectedNumber {
418 found: format!("{}", value),
419 }),
420 }
421 }
422}
423
424impl TryFrom<&Value> for usize {
425 type Error = EvalError;
426
427 fn try_from(value: &Value) -> Result<Self, Self::Error> {
428 match value {
429 Value::Int(i) if *i >= 0 => Ok(*i as usize),
430 Value::Float(f) if f.0 >= 0.0 => Ok(f.0 as usize),
431 Value::Str(s) => {
432 let num = Value::aggressively_to_num(s)?;
433
434 if num < 0.0 {
435 Err(EvalError::ExpectedPositiveNumber {
436 found: format!("{}", value),
437 })
438 } else {
439 Ok(num as usize)
440 }
441 }
442 _ => Err(EvalError::ExpectedPositiveNumber {
443 found: format!("{}", value),
444 }),
445 }
446 }
447}
448
449impl Aggregate {
450 #[cfg(test)]
451 pub fn new(
452 key_columns: &[String],
453 agg_column: String,
454 data: &[(HashMap<String, String>, Value)],
455 ) -> Aggregate {
456 data.iter().for_each(|(row, _value)| {
457 if row.len() != key_columns.len() {
458 panic!("Invalid number of key columns")
459 }
460 key_columns.iter().for_each(|key_column| {
461 if !row.contains_key(key_column) {
462 panic!("New row missing key column: {}", key_column);
463 }
464 });
465 });
466 let raw_data: Vec<HashMap<String, Value>> = data
467 .iter()
468 .map(|(keycols, value)| {
469 let mut new_map: HashMap<String, Value> = keycols
470 .iter()
471 .map(|(keycol, val)| (keycol.clone(), Value::Str(val.clone())))
472 .collect();
473 new_map.insert(agg_column.clone(), value.clone());
474 new_map
475 })
476 .collect();
477 let mut columns = key_columns.to_owned();
478 columns.push(agg_column);
479
480 Aggregate {
481 data: raw_data,
482 columns,
483 }
484 }
485}
486
487impl Record {
488 pub fn put<T: Into<String>>(mut self, key: T, value: Value) -> Record {
489 self.data.insert(key.into(), value);
490 self
491 }
492
493 pub fn put_mut<T: Into<String>>(&mut self, key: T, value: Value) {
494 self.data.insert(key.into(), value);
495 }
496
497 pub fn put_expr(mut self, key: &Expr, value: Value) -> Result<Record, EvalError> {
500 match key {
501 Expr::NestedColumn { ref head, ref rest } => {
502 let mut root_record: &mut Value = if let Some(record) = self.data.get_mut(head) {
503 record
504 } else {
505 return if rest.is_empty() {
506 self.data.insert(head.clone(), value);
507 Ok(self)
508 } else {
509 Err(EvalError::NoValueForKey { key: head.clone() })
510 };
511 };
512
513 let rest_len = rest.len();
514 for (index, value_reference) in rest.iter().enumerate() {
515 match (value_reference, root_record) {
516 (ValueRef::Field(ref key), Value::Obj(map)) => {
517 if !map.contains_key(key) {
518 let is_last = index + 1 == rest_len;
519 return if is_last {
520 map.insert(key.clone(), value);
521 Ok(self)
522 } else {
523 Err(EvalError::NoValueForKey { key: key.clone() })
524 };
525 }
526
527 root_record = map.get_mut(key).expect("exists");
528 }
529 (ValueRef::Field(_), other) => {
530 return Err(EvalError::ExpectedXYZ {
531 expected: "object".to_string(),
532 found: other.render(&DisplayConfig::default()),
533 });
534 }
535 (ValueRef::IndexAt(index), Value::Array(vec)) => {
536 let vec_len: i64 = vec.len().try_into().unwrap();
537 let real_index = if *index < 0 { *index + vec_len } else { *index };
538
539 if real_index < 0 || real_index >= vec_len {
540 return Err(EvalError::IndexOutOfRange { index: *index });
541 }
542 root_record = &mut vec[real_index as usize];
543 }
544 (ValueRef::IndexAt(_), other) => {
545 return Err(EvalError::ExpectedXYZ {
546 expected: "array".to_string(),
547 found: other.render(&DisplayConfig::default()),
548 });
549 }
550 }
551 }
552 *root_record = value;
553 }
554 Expr::BoolUnary(_) => {
557 return Err(EvalError::ExpectedXYZ {
558 expected: "valid expr".to_string(),
559 found: "bool unary expr".to_string(),
560 })
561 }
562 Expr::Comparison(_) => {
563 return Err(EvalError::ExpectedXYZ {
564 expected: "valid expr".to_string(),
565 found: "comparison expr".to_string(),
566 })
567 }
568 Expr::Arithmetic(_) => {
569 return Err(EvalError::ExpectedXYZ {
570 expected: "valid expr".to_string(),
571 found: "arithmetic expr".to_string(),
572 })
573 }
574 Expr::Logical(_) => {
575 return Err(EvalError::ExpectedXYZ {
576 expected: "valid expr".to_string(),
577 found: "logical expr".to_string(),
578 })
579 }
580 Expr::FunctionCall { .. } => {
581 return Err(EvalError::ExpectedXYZ {
582 expected: "valid expr".to_string(),
583 found: "function call".to_string(),
584 })
585 }
586 Expr::IfOp { .. } => {
587 return Err(EvalError::ExpectedXYZ {
588 expected: "valid expr".to_string(),
589 found: "if operator".to_string(),
590 })
591 }
592 Expr::Value(_) => {
593 return Err(EvalError::ExpectedXYZ {
594 expected: "valid expr".to_string(),
595 found: "value expr".to_string(),
596 })
597 }
598 }
599 Ok(self)
600 }
601
602 pub fn new<T: Into<String>>(raw: T) -> Record {
603 Record {
604 data: HashMap::new(),
605 raw: raw.into(),
606 }
607 }
608
609 pub fn ordering<T: Into<Expr> + Send + Sync>(
610 columns: Vec<T>,
611 ) -> impl Fn(&VMap, &VMap) -> Result<Ordering, EvalError> + Send + Sync {
612 let columns: Vec<Expr> = columns.into_iter().map(Into::into).collect();
613 move |rec_l: &VMap, rec_r: &VMap| {
614 for col in &columns {
615 let l_val = col.eval_value(rec_l)?;
616 let r_val = col.eval_value(rec_r)?;
617 let cmp = l_val.cmp(&r_val);
618 if cmp != Ordering::Equal {
619 return Ok(cmp);
620 }
621 }
622 Ok(Ordering::Equal)
623 }
624 }
625
626 pub fn ordering_ref<'a, T: 'a + AsRef<str> + Send + Sync>(
627 columns: &'a [T],
628 ) -> impl Fn(&VMap, &VMap) -> Ordering + 'a + Send + Sync {
629 move |rec_l: &VMap, rec_r: &VMap| {
630 for col in columns {
631 let l_val = rec_l.get(col.as_ref());
632 let r_val = rec_r.get(col.as_ref());
633 let cmp = l_val.cmp(&r_val);
634 if cmp != Ordering::Equal {
635 return cmp;
636 }
637 }
638 Ordering::Equal
639 }
640 }
641}
642
643#[cfg(test)]
644mod tests {
645 use super::*;
646 use maplit::hashmap;
647 use std::str::FromStr;
648
649 #[test]
650 fn render_duration() {
651 let cfg = DisplayConfig { floating_points: 2 };
652
653 assert_eq!("2w", Value::Duration(Duration::weeks(2)).render(&cfg));
654 assert_eq!(
655 "2w2d5h25m4s232ms",
656 Value::Duration(
657 Duration::weeks(2)
658 + Duration::days(2)
659 + Duration::hours(5)
660 + Duration::minutes(25)
661 + Duration::seconds(4)
662 + Duration::milliseconds(232)
663 )
664 .render(&cfg)
665 );
666 }
667
668 #[test]
669 fn record_put_get() {
670 let rec = Record::new("heres some data");
671 let rec = rec.put("key1", Value::Int(9999));
672 assert_eq!(rec.data.get("key1").unwrap(), &Value::Int(9999));
673 assert!(rec.data.get("key2").is_none());
674 assert_eq!(rec.raw, "heres some data");
675 }
676
677 #[test]
678 fn agg() {
679 let agg = Aggregate::new(
680 &["kc1".to_string(), "kc2".to_string()],
681 "count".to_string(),
682 &[(
683 hashmap! {
684 "kc1".to_string() => "k1".to_string(),
685 "kc2".to_string() => "k2".to_string()
686 },
687 Value::Int(100),
688 )],
689 );
690 assert_eq!(agg.data.len(), 1);
691 }
692
693 #[test]
694 fn serialize_vec() {
695 let rec = Value::Array(vec![
696 Value::Bool(false),
697 Value::from_string("123.5"),
698 Value::Array(vec![]),
699 ]);
700 assert_eq!(rec.render(&DisplayConfig::default()), "[false, 123.50, []]");
701 }
702
703 #[test]
704 #[should_panic]
705 fn panic_on_invalid_row() {
706 Aggregate::new(
707 &["k1".to_string(), "k2".to_string()],
708 "count".to_string(),
709 &[(
710 hashmap! {
711 "kc2".to_string() => "k2".to_string()
712 },
713 Value::Int(100),
714 )],
715 );
716 }
717
718 #[test]
719 fn from_string() {
720 assert_eq!(Value::from_string("949919"), Value::Int(949919));
721 assert_eq!(Value::from_string("0.00001"), Value::from_float(0.00001));
722 assert_eq!(
723 Value::from_string("not a number"),
724 Value::Str("not a number".to_string())
725 );
726 assert_eq!(Value::from_string("1 "), Value::Int(1));
727 assert_eq!(Value::from_string("abcd "), Value::Str("abcd".to_owned()));
728 }
729
730 #[test]
731 fn value_ordering() {
732 assert_eq!(
733 Value::from_string("hello").cmp(&Value::Int(0)),
734 Ordering::Greater
735 );
736 }
737
738 #[test]
739 fn test_aggresively_to_num() {
740 assert_eq!(
741 Value::from_string("1,000,000"),
742 Value::Str("1,000,000".to_owned())
743 );
744 assert_eq!(Value::aggressively_to_num("1,000,000"), Ok(1_000_000_f64));
745 assert_eq!(
746 Value::aggressively_to_num("1,000,000.1"),
747 Ok(1_000_000.1_f64)
748 );
749 }
750
751 #[test]
752 fn record_ordering() {
753 let mut r1 = HashMap::<String, Value>::new();
754 r1.insert("k1".to_string(), Value::Int(5));
755 r1.insert("k3".to_string(), Value::from_float(0.1));
756 r1.insert("k2".to_string(), Value::Str("abc".to_string()));
757 let mut r2 = HashMap::<String, Value>::new();
758 r2.insert("k1".to_string(), Value::Int(4));
759 r2.insert("k2".to_string(), Value::Str("xyz".to_string()));
760 r2.insert("k3".to_string(), Value::from_float(0.1));
761 let ord1 = Record::ordering(vec!["k1".to_string(), "k2".to_string()]);
762 assert_eq!(ord1(&r1, &r2), Ok(Ordering::Greater));
763 assert_eq!(ord1(&r1, &r1), Ok(Ordering::Equal));
764 assert_eq!(ord1(&r2, &r1), Ok(Ordering::Less));
765
766 let ord2 = Record::ordering(vec!["k2".to_string(), "k1".to_string()]);
767 assert_eq!(ord2(&r1, &r2), Ok(Ordering::Less));
768 assert_eq!(ord2(&r1, &r1), Ok(Ordering::Equal));
769 assert_eq!(ord2(&r2, &r1), Ok(Ordering::Greater));
770
771 let ord3 = Record::ordering(vec!["k3".to_string()]);
772 assert_eq!(ord3(&r1, &r2), Ok(Ordering::Equal));
773
774 let ord4 = Record::ordering(vec!["k3".to_string(), "k1".to_string()]);
775 assert_eq!(ord4(&r1, &r2), Ok(Ordering::Greater));
776 assert_eq!(ord4(&r1, &r1), Ok(Ordering::Equal));
777 assert_eq!(ord4(&r2, &r1), Ok(Ordering::Less));
778 }
779
780 #[test]
781 fn record_ordering_matching_prefix() {
782 let mut r1 = HashMap::<String, Value>::new();
783 r1.insert("k1".to_string(), Value::Int(5));
784 r1.insert("k2".to_string(), Value::from_float(6.0));
785
786 let mut r2 = HashMap::<String, Value>::new();
787 r2.insert("k1".to_string(), Value::from_float(5.0));
788 r2.insert("k2".to_string(), Value::Int(7));
789
790 let ord = Record::ordering(vec!["k1".to_string(), "k2".to_string()]);
791 assert_eq!(ord(&r1, &r2), Ok(Ordering::Less));
792 }
793
794 #[test]
795 fn arithmetic() {
796 assert_eq!(
797 Value::from_float(5.),
798 (Value::from_float(4.) + Value::from_float(1.)).unwrap()
799 );
800 assert_eq!(Value::Int(5), (Value::Int(4) + Value::Int(1)).unwrap());
801 assert_eq!(
802 Value::from_float(5.),
803 (Value::Int(4) + Value::from_float(1.0)).unwrap()
804 );
805 assert_eq!(
806 Value::from_float(5.),
807 (Value::from_float(4.) + Value::Int(1)).unwrap()
808 );
809
810 assert_eq!(
811 Value::from_float(3.),
812 (Value::from_float(4.) - Value::from_float(1.)).unwrap()
813 );
814 assert_eq!(Value::Int(3), (Value::Int(4) - Value::Int(1)).unwrap());
815 assert_eq!(
816 Value::from_float(3.),
817 (Value::Int(4) - Value::from_float(1.0)).unwrap()
818 );
819 assert_eq!(
820 Value::from_float(3.),
821 (Value::from_float(4.) - Value::Int(1)).unwrap()
822 );
823
824 assert_eq!(
825 Value::from_float(4.),
826 (Value::from_float(4.) * Value::from_float(1.)).unwrap()
827 );
828 assert_eq!(Value::Int(4), (Value::Int(4) * Value::Int(1)).unwrap());
829 assert_eq!(
830 Value::from_float(4.),
831 (Value::Int(4) * Value::from_float(1.0)).unwrap()
832 );
833 assert_eq!(
834 Value::from_float(4.),
835 (Value::from_float(4.) * Value::Int(1)).unwrap()
836 );
837
838 assert_eq!(
839 Value::from_float(2.),
840 (Value::from_float(4.) / Value::from_float(2.)).unwrap()
841 );
842 assert_eq!(Value::Int(2), (Value::Int(4) / Value::Int(2)).unwrap());
843 assert_eq!(
844 Value::from_float(2.),
845 (Value::Int(4) / Value::from_float(2.0)).unwrap()
846 );
847 assert_eq!(
848 Value::from_float(2.),
849 (Value::from_float(4.) / Value::Int(2)).unwrap()
850 );
851
852 assert_eq!(
853 Value::Duration(Duration::days(1)),
854 (Value::DateTime(DateTime::<Utc>::from_str("2021-08-11T00:00:00Z").unwrap())
855 - Value::DateTime(DateTime::<Utc>::from_str("2021-08-10T00:00:00Z").unwrap()))
856 .unwrap()
857 );
858 assert_eq!(
859 Value::Duration(Duration::days(1)),
860 (Value::Duration(Duration::days(2)) - Value::Duration(Duration::days(1))).unwrap()
861 );
862 assert_eq!(
863 Value::Duration(Duration::days(3)),
864 (Value::Duration(Duration::days(2)) + Value::Duration(Duration::days(1))).unwrap()
865 );
866 assert_eq!(
867 Value::Duration(Duration::days(4)),
868 (Value::Duration(Duration::days(2)) * Value::Int(2)).unwrap()
869 );
870 assert_eq!(
871 Value::Duration(Duration::days(1)),
872 (Value::Duration(Duration::days(2)) / Value::Int(2)).unwrap()
873 );
874 }
875}