rpn_cli/calc/
value.rs

1use crate::calc::context::{Context, Format};
2use crate::calc::meaning::Meaning;
3use crate::error::MyResult;
4use crate::regex;
5use crate::util::text::{create_padding, remove_char};
6use big_rational_str::BigRationalExt;
7use chrono::{DateTime, Duration, NaiveDateTime};
8use num::traits::Inv;
9use num::*;
10use regex::{Captures, Match};
11use std::cell::RefCell;
12use std::fmt::{Debug, Formatter};
13use std::iter::zip;
14use std::ops::{BitAnd, BitOr, BitXor, Div, Mul, Sub};
15use std::rc::Rc;
16use std::time::SystemTime;
17
18pub type ValueRef = Rc<RefCell<Value>>;
19
20#[derive(PartialEq)]
21pub struct Value {
22    pub number: Option<BigRational>,
23    pub meaning: Meaning,
24    pub variable: Option<String>,
25    pub comment: Option<String>,
26}
27
28const CHUNK_DIGITS: usize = 8;
29const CHUNK_VALUE: usize = 0x1_0000_0000;
30const ROUNDING_LIMIT: usize = 6;
31
32// noinspection RsLift
33impl Value {
34    pub const fn new(number: Option<BigRational>) -> Self {
35        Self {
36            number,
37            meaning: Meaning::Plain,
38            variable: None,
39            comment: None,
40        }
41    }
42
43    pub fn with_meaning(mut self, meaning: Meaning) -> Self {
44        self.meaning = meaning;
45        self
46    }
47
48    pub fn set_meaning(&mut self, meaning: Meaning) {
49        self.meaning = meaning;
50    }
51
52    pub fn with_variable(mut self, variable: &str) -> Self {
53        self.variable = Some(String::from(variable));
54        self
55    }
56
57    pub fn set_variable(&mut self, variable: &str) {
58        self.variable = Some(String::from(variable));
59    }
60
61    pub fn with_comment(mut self, comment: &str) -> Self {
62        self.comment = Some(String::from(comment));
63        self
64    }
65
66    pub fn set_comment(&mut self, comment: &str) {
67        self.comment = Some(String::from(comment));
68    }
69
70    fn with_rounding(mut self) -> Self {
71        if let Some(number) = &self.number {
72            if let Some(multiplier) = Self::measure_multiplier(number) {
73                if let Some(number) = number.checked_mul(&multiplier) {
74                    let number = number.round();
75                    if let Some(number) = number.checked_div(&multiplier) {
76                        self.number = Some(number);
77                    }
78                }
79            }
80        }
81        self
82    }
83
84    fn measure_multiplier(number: &BigRational) -> Option<BigRational> {
85        let string = big_rational_str::big_rational_ref_to_string(number);
86        if let Some(period) = string.find('.') {
87            let string = remove_char(&string, period);
88            for offset in 1..=ROUNDING_LIMIT {
89                if let Some((start, count)) = Self::measure_offset(&string, offset) {
90                    if let Some(start) = start.checked_sub(period) {
91                        if let Some(remain) = string.len().checked_sub(start + count) {
92                            if remain >= count * 2 {
93                                let multiplier = BigInt::from(10)
94                                    .pow(start as u32);
95                                let multiplier = BigInt::from(10)
96                                    .pow(offset as u32)
97                                    .sub(&BigInt::from(1))
98                                    .mul(&multiplier);
99                                return Some(BigRational::from_integer(multiplier));
100                            }
101                        }
102                    }
103                }
104            }
105        }
106        None
107    }
108
109    // Span:      <------->
110    // Left:  19994564564564564832246034753933155512726838401327...
111    // Right: 94564564564564832246034753933155512726838401327630...
112
113    fn measure_offset(string: &str, offset: usize) -> Option<(usize, usize)> {
114        let left = string.chars();
115        let right = string.chars().skip(offset);
116        let mut span = None;
117        for (index, (left, right)) in zip(left, right).enumerate() {
118            if let Some((start, count)) = span {
119                if left == right {
120                    span = Some((start, count + 1));
121                } else if count >= ROUNDING_LIMIT {
122                    return span;
123                } else {
124                    span = None;
125                }
126            } else {
127                if left == right {
128                    span = Some((index, 0));
129                }
130            }
131        }
132        None
133    }
134
135    pub fn from_string(number: &str) -> MyResult<Self> {
136        if number.starts_with("0x") || number.starts_with("0X") {
137            Self::from_hexadecimal(&number[2..])
138        } else if let Some(value) = Self::from_time(number) {
139            Ok(value)
140        } else if let Some(value) = Self::from_delta(number) {
141            Ok(value)
142        } else if let Some(number) = number.strip_prefix(".") {
143            let number = format!("0.{}", number);
144            Self::from_decimal(&number)
145        } else if let Some(number) = number.strip_prefix("-.") {
146            let number = format!("-0.{}", number);
147            Self::from_decimal(&number)
148        } else {
149            Self::from_decimal(number)
150        }
151    }
152
153    fn from_time(time: &str) -> Option<Self> {
154        if let Some(time) = Self::parse_time(time) {
155            let numer = time.and_utc().timestamp_millis();
156            let numer = BigInt::from(numer);
157            let denom = BigInt::from(1000);
158            let number = BigRational::new(numer, denom);
159            let value = Self::new(Some(number)).with_meaning(Meaning::Time);
160            return Some(value);
161        }
162        None
163    }
164
165    fn parse_time(time: &str) -> Option<NaiveDateTime> {
166        let regex = regex!(r#"^(\d+-\d+-\d+T\d+:\d+(:\d+(\.\d+)?)?)Z?$"#);
167        if let Some(captures) = regex.captures(time) {
168            let time = captures.get(1).as_ref().map(Match::as_str).unwrap_or_default();
169            let format = if captures.get(2).is_none() {
170                "%Y-%m-%dT%H:%M"
171            } else if captures.get(3).is_none() {
172                "%Y-%m-%dT%H:%M:%S"
173            } else {
174                "%Y-%m-%dT%H:%M:%S%.f" // "%.f" not ".%f"
175            };
176            return NaiveDateTime::parse_from_str(time, format).ok();
177        }
178        None
179    }
180
181    fn from_delta(delta: &str) -> Option<Self> {
182        if let Some(delta) = Self::parse_delta(delta) {
183            let numer = delta.num_milliseconds();
184            let numer = BigInt::from(numer);
185            let denom = BigInt::from(1000);
186            let number = BigRational::new(numer, denom);
187            let value = Self::new(Some(number)).with_meaning(Meaning::Delta);
188            return Some(value);
189        }
190        None
191    }
192
193    fn parse_delta(delta: &str) -> Option<Duration> {
194        let regex = regex!(r#"^(-)?(?:(?:(\d+)[T:])?(\d+):)?(\d+):(\d+)(?:\.(\d+))?$"#);
195        if let Some(captures) = regex.captures(delta) {
196            let negative = captures.get(1).is_some();
197            let days = Self::parse_capture(&captures, 2, None);
198            let hours = Self::parse_capture(&captures, 3, None) + (days * 24);
199            let minutes = Self::parse_capture(&captures, 4, None) + (hours * 60);
200            let seconds = Self::parse_capture(&captures, 5, None) + (minutes * 60);
201            let nanos = Self::parse_capture(&captures, 6, Some(9)) + (seconds * 1_000_000_000);
202            let delta = Duration::nanoseconds(nanos);
203            let delta = if negative { -delta } else { delta };
204            return Some(delta);
205        }
206        None
207    }
208
209    fn parse_capture(captures: &Captures, index: usize, expected: Option<usize>) -> i64 {
210        if let Some(capture) = captures.get(index) {
211            let number = capture.as_str().parse::<i64>().unwrap_or_default();
212            if let Some(expected) = expected {
213                let length = capture.as_str().len();
214                if let Some(diff) = expected.checked_sub(length) {
215                    return number * pow(10, diff);
216                }
217                if let Some(diff) = length.checked_sub(expected) {
218                    return number / pow(10, diff);
219                }
220            }
221            return number;
222        }
223        0
224    }
225
226    fn from_decimal(number: &str) -> MyResult<Self> {
227        let number = number.replace(&[',', '_'], "");
228        let number = BigRational::from_dec_str(&number)?;
229        let value = Self::new(Some(number));
230        Ok(value)
231    }
232
233    fn from_hexadecimal(number: &str) -> MyResult<Self> {
234        let number = number.replace(&[',', '_'], "");
235        let number = BigInt::from_str_radix(&number, 16)?;
236        let number = BigRational::from_integer(number);
237        let value = Self::new(Some(number));
238        Ok(value)
239    }
240
241    pub fn to_strings(&self, context: &Context) -> (String, String, Option<String>, Option<String>) {
242        if let Some(number) = &self.number {
243            self.format_ratio(context, number)
244        } else {
245            (String::from("NaN"), String::from(""), self.variable.clone(), self.comment.clone())
246        }
247    }
248
249    fn format_ratio(
250        &self,
251        context: &Context,
252        number: &BigRational,
253    ) -> (String, String, Option<String>, Option<String>) {
254        if self.meaning == Meaning::Time {
255            let number = number * BigInt::from(1000);
256            let number = number.to_i64().unwrap_or_default();
257            let number = Self::format_time(number);
258            self.format_split(context, number)
259        } else if self.meaning == Meaning::Delta {
260            let number = number * BigInt::from(1000);
261            let number = number.to_i64().unwrap_or_default();
262            let number = Self::format_delta(number);
263            self.format_split(context, number)
264        } else if let Format::Base16(chunks) = context.format {
265            let number = number.to_integer();
266            let number = Self::format_hexadecimal(number, chunks, context.sep);
267            (number, String::from(""), self.variable.clone(), self.comment.clone())
268        } else if let Some(dp) = context.dp {
269            let power = BigInt::from(10).pow(dp as u32);
270            let number = number.mul(&power).round().div(&power);
271            let number = big_rational_str::big_rational_to_string(number);
272            self.format_split(context, number)
273        } else {
274            let number = big_rational_str::big_rational_ref_to_string(number);
275            self.format_split(context, number)
276        }
277    }
278
279    fn format_time(millis: i64) -> String {
280        let time = DateTime::from_timestamp_millis(millis).unwrap_or_default();
281        time.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string()
282    }
283
284    fn format_delta(millis: i64) -> String {
285        let (minus, millis) = (if millis < 0 { "-" } else { "" }, abs(millis));
286        let (seconds, millis) = (millis / 1000, millis % 1000);
287        let (minutes, seconds) = (seconds / 60, seconds % 60);
288        let (hours, minutes) = (minutes / 60, minutes % 60);
289        let (days, hours) = (hours / 24, hours % 24);
290        if days != 0 {
291            format!("{}{}T{:02}:{:02}:{:02}.{:03}", minus, days, hours, minutes, seconds, millis)
292        } else if hours != 0 {
293            format!("{}{:02}:{:02}:{:02}.{:03}", minus, hours, minutes, seconds, millis)
294        } else if minutes != 0 {
295            format!("{}{:02}:{:02}.{:03}", minus, minutes, seconds, millis)
296        } else {
297            format!("{}{:02}.{:03}", minus, seconds, millis)
298        }
299    }
300
301    fn format_hexadecimal(
302        mut number: BigInt,
303        chunks: usize,
304        sep: bool,
305    ) -> String {
306        if number.is_negative() {
307            let range = BigInt::from(CHUNK_VALUE).pow(chunks as u32);
308            number += range;
309        }
310        let number = format!("{:x}", number);
311        let padding = create_padding('0', chunks * CHUNK_DIGITS, number.len(), 0);
312        if sep {
313            let number = format!("{}{}", padding, number);
314            let chunks = number.as_bytes()
315                .chunks(CHUNK_DIGITS)
316                .map(std::str::from_utf8);
317            std::iter::once(Ok("0x"))
318                .chain(chunks)
319                .collect::<Result<Vec<&str>, _>>()
320                .unwrap_or_default()
321                .join(",")
322        } else {
323            format!("0x{}{}", padding, number)
324        }
325    }
326
327    fn format_split(
328        &self,
329        context: &Context,
330        number: String,
331    ) -> (String, String, Option<String>, Option<String>) {
332        let index = number.find('.').unwrap_or(number.len());
333        let (integer, fraction) = number.split_at(index);
334        let integer = self.modify_integer(context, integer);
335        let fraction = self.modify_fraction(context, fraction);
336        (integer, fraction, self.variable.clone(), self.comment.clone())
337    }
338
339    fn modify_integer(&self, context: &Context, number: &str) -> String {
340        if self.meaning == Meaning::Plain && context.sep {
341            let index = if number.starts_with('-') { 1 } else { 0 };
342            let (sign, number) = number.split_at(index);
343            let number = number.as_bytes()
344                .rchunks(3)
345                .rev()
346                .map(std::str::from_utf8)
347                .collect::<Result<Vec<&str>, _>>()
348                .unwrap_or_default()
349                .join(",");
350            return format!("{}{}", sign, number);
351        }
352        String::from(number)
353    }
354
355    fn modify_fraction(&self, context: &Context, number: &str) -> String {
356        if self.meaning == Meaning::Plain {
357            if let Some(dp) = context.dp {
358                if !number.is_empty() || dp > 0 {
359                    let index = if number.starts_with('.') { 1 } else { 0 };
360                    let number = &number[index..];
361                    let dp = dp as usize;
362                    return ".".chars()
363                        .chain(number.chars().take(dp))
364                        .chain(std::iter::repeat('0'))
365                        .take(dp + 1)
366                        .collect::<String>();
367                }
368            }
369        }
370        String::from(number)
371    }
372
373    pub fn measure_hexadecimal(&self) -> usize {
374        if let Some(number) = &self.number {
375            let number = number.to_integer();
376            Self::count_hexadecimal(number)
377        } else {
378            1
379        }
380    }
381
382    fn count_hexadecimal(mut number: BigInt) -> usize {
383        if number.is_negative() {
384            number = number.abs() - 1;
385        }
386        let count = number.iter_u32_digits().count().max(1);
387        let chunk = number.iter_u32_digits().last().unwrap_or_default();
388        if chunk & 0x80000000 != 0 { count + 1 } else { count }
389    }
390
391    fn perform_unary(
392        value: ValueRef,
393        meaning: Meaning,
394        function: fn(&BigRational) -> Option<BigRational>,
395    ) -> ValueRef {
396        if let Some(number) = &value.borrow().number {
397            let result = Self::new(function(number)).with_rounding().with_meaning(meaning);
398            return Rc::new(RefCell::new(result));
399        }
400        value
401    }
402
403    fn perform_binary(
404        lhs: ValueRef,
405        rhs: ValueRef,
406        meaning: Meaning,
407        function: fn(&BigRational, &BigRational) -> Option<BigRational>,
408    ) -> ValueRef {
409        if let Some(lhs) = &lhs.borrow().number {
410            if let Some(rhs) = &rhs.borrow().number {
411                let result = Self::new(function(lhs, rhs)).with_rounding().with_meaning(meaning);
412                return Rc::new(RefCell::new(result));
413            }
414            return rhs;
415        }
416        lhs
417    }
418
419    //       | Plain Delta Time
420    // ------+------------------
421    // Plain | Plain Delta Time
422    // Delta | Delta Delta Time
423    // Time  | Time  Time    -
424
425    pub fn calc_add(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
426        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pdt, Meaning::ddt, Meaning::ttx)?;
427        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_add(&y));
428        Ok(result)
429    }
430
431    //       | Plain Delta Time
432    // ------+------------------
433    // Plain | Plain Delta   -
434    // Delta | Delta Delta   -
435    // Time  | Time  Time  Delta
436
437    pub fn calc_sub(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
438        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pdx, Meaning::ddx, Meaning::ttd)?;
439        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_sub(&y));
440        Ok(result)
441    }
442
443    //       | Plain Delta Time
444    // ------+------------------
445    // Plain | Plain Delta   -
446    // Delta | Delta   -     -
447    // Time  |   -     -     -
448
449    pub fn calc_mul(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
450        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pdx, Meaning::dxx, Meaning::xxx)?;
451        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_mul(&y));
452        Ok(result)
453    }
454
455    //       | Plain Delta Time
456    // ------+------------------
457    // Plain | Plain   -     -
458    // Delta | Delta   -     -
459    // Time  |   -     -     -
460
461    pub fn calc_div(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
462        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::dxx, Meaning::xxx)?;
463        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| x.checked_div(&y));
464        Ok(result)
465    }
466
467    pub fn calc_mod(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
468        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::dxx, Meaning::xxx)?;
469        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_mod);
470        Ok(result)
471    }
472
473    fn checked_mod(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
474        lhs.checked_div(rhs)
475            .map(|result| &result - result.to_integer())
476            .map(|result| result * rhs)
477    }
478
479    // Plain | Plain
480    // Delta | Delta
481    // Time  |   -
482
483    pub fn calc_neg(value: ValueRef) -> MyResult<ValueRef> {
484        let meaning = value.borrow().meaning.pdx()?;
485        let result = Self::perform_unary(value, meaning, |x| Some(-x));
486        Ok(result)
487    }
488
489    // Plain | Plain
490    // Delta |   -
491    // Time  |   -
492
493    pub fn calc_inv(value: ValueRef) -> MyResult<ValueRef> {
494        let meaning = value.borrow().meaning.pxx()?;
495        let result = Self::perform_unary(value, meaning, Self::checked_inv);
496        Ok(result)
497    }
498
499    fn checked_inv(number: &BigRational) -> Option<BigRational> {
500        if number.is_zero() { None } else { Some(number.inv()) }
501    }
502
503    //       | Plain Delta Time
504    // ------+------------------
505    // Plain | Plain   -     -
506    // Delta |   -     -     -
507    // Time  |   -     -     -
508
509    pub fn calc_pow(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
510        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
511        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_pow);
512        Ok(result)
513    }
514
515    fn checked_pow(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
516        if rhs.is_integer() {
517            if let Some(rhs) = rhs.to_i32() {
518                return Some(lhs.pow(rhs));
519            }
520        } else {
521            if let Some(lhs) = lhs.to_f64() {
522                if let Some(rhs) = rhs.to_f64() {
523                    let result = f64::powf(lhs, rhs);
524                    return BigRational::from_f64(result);
525                }
526            }
527        }
528        None
529    }
530
531    // Plain | Plain
532    // Delta |   -
533    // Time  |   -
534
535    pub fn calc_sqrt(value: ValueRef) -> MyResult<ValueRef> {
536        let meaning = value.borrow().meaning.pxx()?;
537        let result = Self::perform_unary(value, meaning, Self::checked_sqrt);
538        Ok(result)
539    }
540
541    fn checked_sqrt(number: &BigRational) -> Option<BigRational> {
542        if let Some(number) = number.to_f64() {
543            let result = number.sqrt();
544            return BigRational::from_f64(result);
545        }
546        None
547    }
548
549    pub fn calc_sum(values: Vec<ValueRef>) -> MyResult<ValueRef> {
550        let mut result = BigRational::from(BigInt::zero());
551        for value in values {
552            if let Some(number) = &value.borrow().number {
553                result += number;
554            }
555        }
556        let result = Self::new(Some(result)).with_rounding();
557        Ok(Rc::new(RefCell::new(result)))
558    }
559
560    pub fn calc_prod(values: Vec<ValueRef>) -> MyResult<ValueRef> {
561        let mut result = BigRational::from(BigInt::one());
562        for value in values {
563            if let Some(number) = &value.borrow().number {
564                result *= number;
565            }
566        }
567        let result = Self::new(Some(result)).with_rounding();
568        Ok(Rc::new(RefCell::new(result)))
569    }
570
571    //       | Plain Delta Time
572    // ------+------------------
573    // Plain | Plain   -     -
574    // Delta |   -     -     -
575    // Time  |   -     -     -
576
577    pub fn calc_and(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
578        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
579        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_and);
580        Ok(result)
581    }
582
583    pub fn calc_or(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
584        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
585        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_or);
586        Ok(result)
587    }
588
589    pub fn calc_xor(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
590        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
591        let result = Self::perform_binary(lhs, rhs, meaning, Self::checked_xor);
592        Ok(result)
593    }
594
595    fn checked_and(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
596        let lhs = lhs.to_integer();
597        let rhs = rhs.to_integer();
598        let result = lhs.bitand(rhs);
599        Some(BigRational::from(result))
600    }
601
602    fn checked_or(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
603        let lhs = lhs.to_integer();
604        let rhs = rhs.to_integer();
605        let result = lhs.bitor(rhs);
606        Some(BigRational::from(result))
607    }
608
609    fn checked_xor(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
610        let lhs = lhs.to_integer();
611        let rhs = rhs.to_integer();
612        let result = lhs.bitxor(rhs);
613        Some(BigRational::from(result))
614    }
615
616    pub fn calc_shl(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
617        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
618        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| Self::checked_shl(x, y));
619        Ok(result)
620    }
621
622    pub fn calc_shr(lhs: ValueRef, rhs: ValueRef) -> MyResult<ValueRef> {
623        let meaning = lhs.borrow().meaning.combine(rhs.borrow().meaning, Meaning::pxx, Meaning::xxx, Meaning::xxx)?;
624        let result = Self::perform_binary(lhs, rhs, meaning, |x, y| Self::checked_shr(x, y));
625        Ok(result)
626    }
627
628    fn checked_shl(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
629        if let Some(rhs) = rhs.to_i32() {
630            let two = BigRational::new(BigInt::from(2), BigInt::from(1));
631            Some(lhs * two.pow(rhs))
632        } else {
633            None
634        }
635    }
636
637    fn checked_shr(lhs: &BigRational, rhs: &BigRational) -> Option<BigRational> {
638        if let Some(rhs) = rhs.to_i32() {
639            let two = BigRational::new(BigInt::from(2), BigInt::from(1));
640            Some(lhs * two.pow(-rhs))
641        } else {
642            None
643        }
644    }
645
646    pub fn calc_now(time: &Option<SystemTime>) -> MyResult<ValueRef> {
647        let time = time.unwrap_or_else(SystemTime::now)
648            .duration_since(SystemTime::UNIX_EPOCH)
649            .unwrap_or_default()
650            .as_millis();
651        let numer = BigInt::from(time);
652        let denom = BigInt::from(1000);
653        let number = BigRational::new(numer, denom);
654        let result = Self::new(Some(number)).with_meaning(Meaning::Time);
655        Ok(Rc::new(RefCell::new(result)))
656    }
657
658    pub fn cast_plain(value: ValueRef) -> MyResult<()> {
659        value.borrow_mut().set_meaning(Meaning::Plain);
660        Ok(())
661    }
662
663    pub fn cast_delta(value: ValueRef) -> MyResult<()> {
664        value.borrow_mut().set_meaning(Meaning::Delta);
665        Ok(())
666    }
667
668    pub fn cast_time(value: ValueRef) -> MyResult<()> {
669        value.borrow_mut().set_meaning(Meaning::Time);
670        Ok(())
671    }
672}
673
674impl Default for Value {
675    fn default() -> Self {
676        Self::new(Some(BigRational::zero()))
677    }
678}
679
680impl Clone for Value {
681    fn clone(&self) -> Self {
682        // Clone everything but the variable name.
683        let number = self.number.clone();
684        let mut value = Self::new(number);
685        value.meaning = self.meaning;
686        value.comment = self.comment.clone();
687        value
688    }
689}
690
691impl Debug for Value {
692    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
693        if let Some(number) = &self.number {
694            write!(f, "{}", big_rational_str::big_rational_ref_to_string(number))?;
695        } else {
696            write!(f, "NaN")?;
697        }
698        match self.meaning {
699            Meaning::Plain => (),
700            Meaning::Delta => write!(f, " [delta]")?,
701            Meaning::Time => write!(f, " [time]")?,
702        }
703        if let Some(variable) = &self.variable {
704            write!(f, " = {}", variable)?;
705        }
706        if let Some(comment) = &self.comment {
707            write!(f, " # {}", comment)?;
708        }
709        Ok(())
710    }
711}
712
713#[cfg(test)]
714pub mod tests {
715    use crate::calc::context::{Context, Format};
716    use crate::calc::meaning::Meaning;
717    use crate::calc::value::{Value, ValueRef};
718    use crate::error::{EngineError, MyError, MyResult};
719    use crate::regex;
720    use num::{BigInt, BigRational, CheckedMul, CheckedSub, FromPrimitive, ToPrimitive};
721    use pretty_assertions::assert_eq;
722    use regex::Match;
723    use std::cell::RefCell;
724    use std::rc::Rc;
725
726    const VALUE_NAN: Value = Value::new(None);
727
728    #[test]
729    fn test_decimal_is_created_from_string_no_separator() {
730        assert_eq!(create_value(0, 1), Value::from_string("0").unwrap());
731        assert_eq!(create_value(123456789, 1), Value::from_string("123456789").unwrap());
732        assert_eq!(create_value(-123456789, 1), Value::from_string("-123456789").unwrap());
733        assert_eq!(create_value(123456789, 100), Value::from_string("1234567.89").unwrap());
734        assert_eq!(create_value(-123456789, 100), Value::from_string("-1234567.89").unwrap());
735        assert_eq!(create_value(999, 1000), Value::from_string(".999").unwrap());
736        assert_eq!(create_value(-999, 1000), Value::from_string("-.999").unwrap());
737        assert!(Value::from_string("").is_err());
738        assert!(Value::from_string("foo").is_err());
739    }
740
741    #[test]
742    fn test_decimal_is_created_from_string_with_separator() {
743        assert_eq!(create_value(123456789, 1), Value::from_string("123,456,789").unwrap());
744        assert_eq!(create_value(123456789, 1), Value::from_string("123_456_789").unwrap());
745        assert_eq!(create_value(-123456789, 1), Value::from_string("-123,456,789").unwrap());
746        assert_eq!(create_value(-123456789, 1), Value::from_string("-123_456_789").unwrap());
747        assert_eq!(create_value(123456789, 100), Value::from_string("1,234,567.89").unwrap());
748        assert_eq!(create_value(123456789, 100), Value::from_string("1_234_567.89").unwrap());
749        assert_eq!(create_value(-123456789, 100), Value::from_string("-1,234,567.89").unwrap());
750        assert_eq!(create_value(-123456789, 100), Value::from_string("-1_234_567.89").unwrap());
751    }
752
753    #[test]
754    fn test_hexadecimal_is_created_from_lowercase_no_separator() {
755        assert_eq!(create_value(0, 1), Value::from_string("0x0").unwrap());
756        assert_eq!(create_value(0xffff, 1), Value::from_string("0xffff").unwrap());
757        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0xffffffff").unwrap());
758        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0xffffffffffff").unwrap());
759        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0x0123456789abcdef").unwrap());
760        assert!(Value::from_string("0x").is_err());
761        assert!(Value::from_string("0xfoo").is_err());
762    }
763
764    #[test]
765    fn test_hexadecimal_is_created_from_uppercase_no_separator() {
766        assert_eq!(create_value(0, 1), Value::from_string("0X0").unwrap());
767        assert_eq!(create_value(0xffff, 1), Value::from_string("0XFFFF").unwrap());
768        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0XFFFFFFFF").unwrap());
769        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0XFFFFFFFFFFFF").unwrap());
770        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0X0123456789ABCDEF").unwrap());
771        assert!(Value::from_string("0X").is_err());
772        assert!(Value::from_string("0XFOO").is_err());
773    }
774
775    #[test]
776    fn test_hexadecimal_is_created_from_lowercase_with_separator() {
777        assert_eq!(create_value(0, 1), Value::from_string("0x_0").unwrap());
778        assert_eq!(create_value(0xffff, 1), Value::from_string("0x_ffff").unwrap());
779        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0x_ffff_ffff").unwrap());
780        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0x,ffff,ffff,ffff").unwrap());
781        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0x,0123,4567,89ab,cdef").unwrap());
782        assert!(Value::from_string("0x_").is_err());
783        assert!(Value::from_string("0x,foo").is_err());
784    }
785
786    #[test]
787    fn test_hexadecimal_is_created_from_uppercase_with_separator() {
788        assert_eq!(create_value(0, 1), Value::from_string("0X_0").unwrap());
789        assert_eq!(create_value(0xffff, 1), Value::from_string("0X_FFFF").unwrap());
790        assert_eq!(create_value(0xffffffff, 1), Value::from_string("0X_FFFF_FFFF").unwrap());
791        assert_eq!(create_value(0xffffffffffff, 1), Value::from_string("0X,FFFF,FFFF,FFFF").unwrap());
792        assert_eq!(create_value(0x0123456789abcdef, 1), Value::from_string("0X,0123,4567,89AB,CDEF").unwrap());
793        assert!(Value::from_string("0X_").is_err());
794        assert!(Value::from_string("0X,FOO").is_err());
795    }
796
797    #[test]
798    fn test_time_is_created_from_string_no_zulu() {
799        let summer1 = Value::from_string("2024-06-30T23:59").unwrap();
800        let summer2 = Value::from_string("2024-06-30T23:59:59").unwrap();
801        let summer3 = Value::from_string("2024-06-30T23:59:59.999").unwrap();
802        let winter1 = Value::from_string("2024-12-31T23:59").unwrap();
803        let winter2 = Value::from_string("2024-12-31T23:59:59").unwrap();
804        let winter3 = Value::from_string("2024-12-31T23:59:59.999").unwrap();
805        assert_eq!(create_value(1719791940000, 1000).with_meaning(Meaning::Time), summer1);
806        assert_eq!(create_value(1719791999000, 1000).with_meaning(Meaning::Time), summer2);
807        assert_eq!(create_value(1719791999999, 1000).with_meaning(Meaning::Time), summer3);
808        assert_eq!(create_value(1735689540000, 1000).with_meaning(Meaning::Time), winter1);
809        assert_eq!(create_value(1735689599000, 1000).with_meaning(Meaning::Time), winter2);
810        assert_eq!(create_value(1735689599999, 1000).with_meaning(Meaning::Time), winter3);
811    }
812
813    #[test]
814    fn test_time_is_created_from_string_with_zulu() {
815        let summer1 = Value::from_string("2024-06-30T23:59Z").unwrap();
816        let summer2 = Value::from_string("2024-06-30T23:59:59Z").unwrap();
817        let summer3 = Value::from_string("2024-06-30T23:59:59.999Z").unwrap();
818        let winter1 = Value::from_string("2024-12-31T23:59Z").unwrap();
819        let winter2 = Value::from_string("2024-12-31T23:59:59Z").unwrap();
820        let winter3 = Value::from_string("2024-12-31T23:59:59.999Z").unwrap();
821        assert_eq!(create_value(1719791940000, 1000).with_meaning(Meaning::Time), summer1);
822        assert_eq!(create_value(1719791999000, 1000).with_meaning(Meaning::Time), summer2);
823        assert_eq!(create_value(1719791999999, 1000).with_meaning(Meaning::Time), summer3);
824        assert_eq!(create_value(1735689540000, 1000).with_meaning(Meaning::Time), winter1);
825        assert_eq!(create_value(1735689599000, 1000).with_meaning(Meaning::Time), winter2);
826        assert_eq!(create_value(1735689599999, 1000).with_meaning(Meaning::Time), winter3);
827    }
828
829    #[test]
830    fn test_delta_is_created_from_string_old_format() {
831        let minutes1 = Value::from_string("34:56").unwrap();
832        let minutes2 = Value::from_string("34:56.7").unwrap();
833        let minutes3 = Value::from_string("34:56.789").unwrap();
834        let minutes4 = Value::from_string("-34:56").unwrap();
835        let minutes5 = Value::from_string("-34:56.7").unwrap();
836        let minutes6 = Value::from_string("-34:56.789").unwrap();
837        let hours1 = Value::from_string("12:34:56").unwrap();
838        let hours2 = Value::from_string("12:34:56.7").unwrap();
839        let hours3 = Value::from_string("12:34:56.789").unwrap();
840        let hours4 = Value::from_string("-12:34:56").unwrap();
841        let hours5 = Value::from_string("-12:34:56.7").unwrap();
842        let hours6 = Value::from_string("-12:34:56.789").unwrap();
843        let days1 = Value::from_string("9:12:34:56").unwrap();
844        let days2 = Value::from_string("9:12:34:56.7").unwrap();
845        let days3 = Value::from_string("9:12:34:56.789").unwrap();
846        let days4 = Value::from_string("-9:12:34:56").unwrap();
847        let days5 = Value::from_string("-9:12:34:56.7").unwrap();
848        let days6 = Value::from_string("-9:12:34:56.789").unwrap();
849        assert_eq!(create_value(2096000, 1000).with_meaning(Meaning::Delta), minutes1);
850        assert_eq!(create_value(2096700, 1000).with_meaning(Meaning::Delta), minutes2);
851        assert_eq!(create_value(2096789, 1000).with_meaning(Meaning::Delta), minutes3);
852        assert_eq!(create_value(-2096000, 1000).with_meaning(Meaning::Delta), minutes4);
853        assert_eq!(create_value(-2096700, 1000).with_meaning(Meaning::Delta), minutes5);
854        assert_eq!(create_value(-2096789, 1000).with_meaning(Meaning::Delta), minutes6);
855        assert_eq!(create_value(45296000, 1000).with_meaning(Meaning::Delta), hours1);
856        assert_eq!(create_value(45296700, 1000).with_meaning(Meaning::Delta), hours2);
857        assert_eq!(create_value(45296789, 1000).with_meaning(Meaning::Delta), hours3);
858        assert_eq!(create_value(-45296000, 1000).with_meaning(Meaning::Delta), hours4);
859        assert_eq!(create_value(-45296700, 1000).with_meaning(Meaning::Delta), hours5);
860        assert_eq!(create_value(-45296789, 1000).with_meaning(Meaning::Delta), hours6);
861        assert_eq!(create_value(822896000, 1000).with_meaning(Meaning::Delta), days1);
862        assert_eq!(create_value(822896700, 1000).with_meaning(Meaning::Delta), days2);
863        assert_eq!(create_value(822896789, 1000).with_meaning(Meaning::Delta), days3);
864        assert_eq!(create_value(-822896000, 1000).with_meaning(Meaning::Delta), days4);
865        assert_eq!(create_value(-822896700, 1000).with_meaning(Meaning::Delta), days5);
866        assert_eq!(create_value(-822896789, 1000).with_meaning(Meaning::Delta), days6);
867    }
868
869    #[test]
870    fn test_delta_is_created_from_string_new_format() {
871        let days1 = Value::from_string("9T12:34:56").unwrap();
872        let days2 = Value::from_string("9T12:34:56.7").unwrap();
873        let days3 = Value::from_string("9T12:34:56.789").unwrap();
874        let days4 = Value::from_string("-9T12:34:56").unwrap();
875        let days5 = Value::from_string("-9T12:34:56.7").unwrap();
876        let days6 = Value::from_string("-9T12:34:56.789").unwrap();
877        assert_eq!(create_value(822896000, 1000).with_meaning(Meaning::Delta), days1);
878        assert_eq!(create_value(822896700, 1000).with_meaning(Meaning::Delta), days2);
879        assert_eq!(create_value(822896789, 1000).with_meaning(Meaning::Delta), days3);
880        assert_eq!(create_value(-822896000, 1000).with_meaning(Meaning::Delta), days4);
881        assert_eq!(create_value(-822896700, 1000).with_meaning(Meaning::Delta), days5);
882        assert_eq!(create_value(-822896789, 1000).with_meaning(Meaning::Delta), days6);
883    }
884
885    #[test]
886    fn test_value_with_repeating_zero_or_nine_is_rounded() {
887        let number1 = fudge_ratio(create_ratio(17, 8)).and_then(opposite_ratio); // 1.874999999999999801...
888        let number2 = fudge_ratio(create_ratio(16, 8)).and_then(opposite_ratio); // 1.999999999999999726...
889        let number3 = fudge_ratio(create_ratio(16, 8)); // 2.000000000000000273...
890        let number4 = fudge_ratio(create_ratio(17, 8)); // 2.125000000000000198...
891        assert_eq!(create_value(15, 8), Value::new(number1).with_rounding());
892        assert_eq!(create_value(16, 8), Value::new(number2).with_rounding());
893        assert_eq!(create_value(16, 8), Value::new(number3).with_rounding());
894        assert_eq!(create_value(17, 8), Value::new(number4).with_rounding());
895    }
896
897    #[test]
898    fn test_value_with_repeating_one_to_eight_is_rounded() {
899        let number1 = fudge_ratio(create_ratio(908992, 9000)); // 100.999111111111094...
900        let number2 = fudge_ratio(create_ratio(1088924, 99000)); // 10.999232323232323771...
901        let number3 = fudge_ratio(create_ratio(1997457, 999000)); // 1.999456456456456483...
902        let number4 = fudge_ratio(create_ratio(19995891, 9999000)); // 1.999789078907890437...
903        assert_eq!(create_value(908992, 9000), Value::new(number1).with_rounding());
904        assert_eq!(create_value(1088924, 99000), Value::new(number2).with_rounding());
905        assert_eq!(create_value(1997457, 999000), Value::new(number3).with_rounding());
906        assert_eq!(create_value(19995891, 9999000), Value::new(number4).with_rounding());
907    }
908
909    #[test]
910    fn test_decimal_is_formatted_with_default() {
911        let context = Context::new();
912        assert_eq!((String::from("0"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
913        assert_eq!((String::from("1"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
914        assert_eq!((String::from("12"), String::from(""), None, None), create_value(12, 1).to_strings(&context));
915        assert_eq!((String::from("123"), String::from(""), None, None), create_value(123, 1).to_strings(&context));
916        assert_eq!((String::from("1234"), String::from(""), None, None), create_value(1234, 1).to_strings(&context));
917        assert_eq!((String::from("12345"), String::from(""), None, None), create_value(12345, 1).to_strings(&context));
918        assert_eq!((String::from("123456"), String::from(""), None, None), create_value(123456, 1).to_strings(&context));
919        assert_eq!((String::from("1234567"), String::from(""), None, None), create_value(1234567, 1).to_strings(&context));
920        assert_eq!((String::from("12345678"), String::from(""), None, None), create_value(12345678, 1).to_strings(&context));
921        assert_eq!((String::from("123456789"), String::from(""), None, None), create_value(123456789, 1).to_strings(&context));
922        assert_eq!((String::from("-1"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
923        assert_eq!((String::from("-12"), String::from(""), None, None), create_value(-12, 1).to_strings(&context));
924        assert_eq!((String::from("-123"), String::from(""), None, None), create_value(-123, 1).to_strings(&context));
925        assert_eq!((String::from("-1234"), String::from(""), None, None), create_value(-1234, 1).to_strings(&context));
926        assert_eq!((String::from("-12345"), String::from(""), None, None), create_value(-12345, 1).to_strings(&context));
927        assert_eq!((String::from("-123456"), String::from(""), None, None), create_value(-123456, 1).to_strings(&context));
928        assert_eq!((String::from("-1234567"), String::from(""), None, None), create_value(-1234567, 1).to_strings(&context));
929        assert_eq!((String::from("-12345678"), String::from(""), None, None), create_value(-12345678, 1).to_strings(&context));
930        assert_eq!((String::from("-123456789"), String::from(""), None, None), create_value(-123456789, 1).to_strings(&context));
931        assert_eq!((String::from("0"), String::from(".00001"), None, None), create_value(1, 100000).to_strings(&context));
932        assert_eq!((String::from("0"), String::from(".0001"), None, None), create_value(1, 10000).to_strings(&context));
933        assert_eq!((String::from("0"), String::from(".001"), None, None), create_value(1, 1000).to_strings(&context));
934        assert_eq!((String::from("0"), String::from(".01"), None, None), create_value(1, 100).to_strings(&context));
935        assert_eq!((String::from("0"), String::from(".1"), None, None), create_value(1, 10).to_strings(&context));
936        assert_eq!((String::from("0"), String::from(".4994"), None, None), create_value(49940, 100000).to_strings(&context));
937        assert_eq!((String::from("0"), String::from(".49949"), None, None), create_value(49949, 100000).to_strings(&context));
938        assert_eq!((String::from("0"), String::from(".4995"), None, None), create_value(49950, 100000).to_strings(&context));
939        assert_eq!((String::from("0"), String::from(".49951"), None, None), create_value(49951, 100000).to_strings(&context));
940        assert_eq!((String::from("0"), String::from(".9"), None, None), create_value(9, 10).to_strings(&context));
941        assert_eq!((String::from("0"), String::from(".99"), None, None), create_value(99, 100).to_strings(&context));
942        assert_eq!((String::from("0"), String::from(".999"), None, None), create_value(999, 1000).to_strings(&context));
943        assert_eq!((String::from("0"), String::from(".9999"), None, None), create_value(9999, 10000).to_strings(&context));
944        assert_eq!((String::from("0"), String::from(".99999"), None, None), create_value(99999, 100000).to_strings(&context));
945        assert_eq!((String::from("-0"), String::from(".00001"), None, None), create_value(-1, 100000).to_strings(&context));
946        assert_eq!((String::from("-0"), String::from(".0001"), None, None), create_value(-1, 10000).to_strings(&context));
947        assert_eq!((String::from("-0"), String::from(".001"), None, None), create_value(-1, 1000).to_strings(&context));
948        assert_eq!((String::from("-0"), String::from(".01"), None, None), create_value(-1, 100).to_strings(&context));
949        assert_eq!((String::from("-0"), String::from(".1"), None, None), create_value(-1, 10).to_strings(&context));
950        assert_eq!((String::from("-0"), String::from(".4994"), None, None), create_value(-49940, 100000).to_strings(&context));
951        assert_eq!((String::from("-0"), String::from(".49949"), None, None), create_value(-49949, 100000).to_strings(&context));
952        assert_eq!((String::from("-0"), String::from(".4995"), None, None), create_value(-49950, 100000).to_strings(&context));
953        assert_eq!((String::from("-0"), String::from(".49951"), None, None), create_value(-49951, 100000).to_strings(&context));
954        assert_eq!((String::from("-0"), String::from(".9"), None, None), create_value(-9, 10).to_strings(&context));
955        assert_eq!((String::from("-0"), String::from(".99"), None, None), create_value(-99, 100).to_strings(&context));
956        assert_eq!((String::from("-0"), String::from(".999"), None, None), create_value(-999, 1000).to_strings(&context));
957        assert_eq!((String::from("-0"), String::from(".9999"), None, None), create_value(-9999, 10000).to_strings(&context));
958        assert_eq!((String::from("-0"), String::from(".99999"), None, None), create_value(-99999, 100000).to_strings(&context));
959    }
960
961    #[test]
962    fn test_decimal_is_formatted_with_separator() {
963        let context = Context::new().with_sep(true);
964        assert_eq!((String::from("0"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
965        assert_eq!((String::from("1"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
966        assert_eq!((String::from("12"), String::from(""), None, None), create_value(12, 1).to_strings(&context));
967        assert_eq!((String::from("123"), String::from(""), None, None), create_value(123, 1).to_strings(&context));
968        assert_eq!((String::from("1,234"), String::from(""), None, None), create_value(1234, 1).to_strings(&context));
969        assert_eq!((String::from("12,345"), String::from(""), None, None), create_value(12345, 1).to_strings(&context));
970        assert_eq!((String::from("123,456"), String::from(""), None, None), create_value(123456, 1).to_strings(&context));
971        assert_eq!((String::from("1,234,567"), String::from(""), None, None), create_value(1234567, 1).to_strings(&context));
972        assert_eq!((String::from("12,345,678"), String::from(""), None, None), create_value(12345678, 1).to_strings(&context));
973        assert_eq!((String::from("123,456,789"), String::from(""), None, None), create_value(123456789, 1).to_strings(&context));
974        assert_eq!((String::from("-1"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
975        assert_eq!((String::from("-12"), String::from(""), None, None), create_value(-12, 1).to_strings(&context));
976        assert_eq!((String::from("-123"), String::from(""), None, None), create_value(-123, 1).to_strings(&context));
977        assert_eq!((String::from("-1,234"), String::from(""), None, None), create_value(-1234, 1).to_strings(&context));
978        assert_eq!((String::from("-12,345"), String::from(""), None, None), create_value(-12345, 1).to_strings(&context));
979        assert_eq!((String::from("-123,456"), String::from(""), None, None), create_value(-123456, 1).to_strings(&context));
980        assert_eq!((String::from("-1,234,567"), String::from(""), None, None), create_value(-1234567, 1).to_strings(&context));
981        assert_eq!((String::from("-12,345,678"), String::from(""), None, None), create_value(-12345678, 1).to_strings(&context));
982        assert_eq!((String::from("-123,456,789"), String::from(""), None, None), create_value(-123456789, 1).to_strings(&context));
983        assert_eq!((String::from("0"), String::from(".00001"), None, None), create_value(1, 100000).to_strings(&context));
984        assert_eq!((String::from("0"), String::from(".0001"), None, None), create_value(1, 10000).to_strings(&context));
985        assert_eq!((String::from("0"), String::from(".001"), None, None), create_value(1, 1000).to_strings(&context));
986        assert_eq!((String::from("0"), String::from(".01"), None, None), create_value(1, 100).to_strings(&context));
987        assert_eq!((String::from("0"), String::from(".1"), None, None), create_value(1, 10).to_strings(&context));
988        assert_eq!((String::from("0"), String::from(".4994"), None, None), create_value(49940, 100000).to_strings(&context));
989        assert_eq!((String::from("0"), String::from(".49949"), None, None), create_value(49949, 100000).to_strings(&context));
990        assert_eq!((String::from("0"), String::from(".4995"), None, None), create_value(49950, 100000).to_strings(&context));
991        assert_eq!((String::from("0"), String::from(".49951"), None, None), create_value(49951, 100000).to_strings(&context));
992        assert_eq!((String::from("0"), String::from(".9"), None, None), create_value(9, 10).to_strings(&context));
993        assert_eq!((String::from("0"), String::from(".99"), None, None), create_value(99, 100).to_strings(&context));
994        assert_eq!((String::from("0"), String::from(".999"), None, None), create_value(999, 1000).to_strings(&context));
995        assert_eq!((String::from("0"), String::from(".9999"), None, None), create_value(9999, 10000).to_strings(&context));
996        assert_eq!((String::from("0"), String::from(".99999"), None, None), create_value(99999, 100000).to_strings(&context));
997        assert_eq!((String::from("-0"), String::from(".00001"), None, None), create_value(-1, 100000).to_strings(&context));
998        assert_eq!((String::from("-0"), String::from(".0001"), None, None), create_value(-1, 10000).to_strings(&context));
999        assert_eq!((String::from("-0"), String::from(".001"), None, None), create_value(-1, 1000).to_strings(&context));
1000        assert_eq!((String::from("-0"), String::from(".01"), None, None), create_value(-1, 100).to_strings(&context));
1001        assert_eq!((String::from("-0"), String::from(".1"), None, None), create_value(-1, 10).to_strings(&context));
1002        assert_eq!((String::from("-0"), String::from(".4994"), None, None), create_value(-49940, 100000).to_strings(&context));
1003        assert_eq!((String::from("-0"), String::from(".49949"), None, None), create_value(-49949, 100000).to_strings(&context));
1004        assert_eq!((String::from("-0"), String::from(".4995"), None, None), create_value(-49950, 100000).to_strings(&context));
1005        assert_eq!((String::from("-0"), String::from(".49951"), None, None), create_value(-49951, 100000).to_strings(&context));
1006        assert_eq!((String::from("-0"), String::from(".9"), None, None), create_value(-9, 10).to_strings(&context));
1007        assert_eq!((String::from("-0"), String::from(".99"), None, None), create_value(-99, 100).to_strings(&context));
1008        assert_eq!((String::from("-0"), String::from(".999"), None, None), create_value(-999, 1000).to_strings(&context));
1009        assert_eq!((String::from("-0"), String::from(".9999"), None, None), create_value(-9999, 10000).to_strings(&context));
1010        assert_eq!((String::from("-0"), String::from(".99999"), None, None), create_value(-99999, 100000).to_strings(&context));
1011    }
1012
1013    #[test]
1014    fn test_decimal_is_formatted_with_precision() {
1015        let context = Context::new().with_dp(Some(3));
1016        assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(0, 1).to_strings(&context));
1017        assert_eq!((String::from("1"), String::from(".000"), None, None), create_value(1, 1).to_strings(&context));
1018        assert_eq!((String::from("12"), String::from(".000"), None, None), create_value(12, 1).to_strings(&context));
1019        assert_eq!((String::from("123"), String::from(".000"), None, None), create_value(123, 1).to_strings(&context));
1020        assert_eq!((String::from("1234"), String::from(".000"), None, None), create_value(1234, 1).to_strings(&context));
1021        assert_eq!((String::from("12345"), String::from(".000"), None, None), create_value(12345, 1).to_strings(&context));
1022        assert_eq!((String::from("123456"), String::from(".000"), None, None), create_value(123456, 1).to_strings(&context));
1023        assert_eq!((String::from("1234567"), String::from(".000"), None, None), create_value(1234567, 1).to_strings(&context));
1024        assert_eq!((String::from("12345678"), String::from(".000"), None, None), create_value(12345678, 1).to_strings(&context));
1025        assert_eq!((String::from("123456789"), String::from(".000"), None, None), create_value(123456789, 1).to_strings(&context));
1026        assert_eq!((String::from("-1"), String::from(".000"), None, None), create_value(-1, 1).to_strings(&context));
1027        assert_eq!((String::from("-12"), String::from(".000"), None, None), create_value(-12, 1).to_strings(&context));
1028        assert_eq!((String::from("-123"), String::from(".000"), None, None), create_value(-123, 1).to_strings(&context));
1029        assert_eq!((String::from("-1234"), String::from(".000"), None, None), create_value(-1234, 1).to_strings(&context));
1030        assert_eq!((String::from("-12345"), String::from(".000"), None, None), create_value(-12345, 1).to_strings(&context));
1031        assert_eq!((String::from("-123456"), String::from(".000"), None, None), create_value(-123456, 1).to_strings(&context));
1032        assert_eq!((String::from("-1234567"), String::from(".000"), None, None), create_value(-1234567, 1).to_strings(&context));
1033        assert_eq!((String::from("-12345678"), String::from(".000"), None, None), create_value(-12345678, 1).to_strings(&context));
1034        assert_eq!((String::from("-123456789"), String::from(".000"), None, None), create_value(-123456789, 1).to_strings(&context));
1035        assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(1, 100000).to_strings(&context));
1036        assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(1, 10000).to_strings(&context));
1037        assert_eq!((String::from("0"), String::from(".001"), None, None), create_value(1, 1000).to_strings(&context));
1038        assert_eq!((String::from("0"), String::from(".010"), None, None), create_value(1, 100).to_strings(&context));
1039        assert_eq!((String::from("0"), String::from(".100"), None, None), create_value(1, 10).to_strings(&context));
1040        assert_eq!((String::from("0"), String::from(".499"), None, None), create_value(49940, 100000).to_strings(&context));
1041        assert_eq!((String::from("0"), String::from(".499"), None, None), create_value(49949, 100000).to_strings(&context));
1042        assert_eq!((String::from("0"), String::from(".500"), None, None), create_value(49950, 100000).to_strings(&context));
1043        assert_eq!((String::from("0"), String::from(".500"), None, None), create_value(49951, 100000).to_strings(&context));
1044        assert_eq!((String::from("0"), String::from(".900"), None, None), create_value(9, 10).to_strings(&context));
1045        assert_eq!((String::from("0"), String::from(".990"), None, None), create_value(99, 100).to_strings(&context));
1046        assert_eq!((String::from("0"), String::from(".999"), None, None), create_value(999, 1000).to_strings(&context));
1047        assert_eq!((String::from("1"), String::from(".000"), None, None), create_value(9999, 10000).to_strings(&context));
1048        assert_eq!((String::from("1"), String::from(".000"), None, None), create_value(99999, 100000).to_strings(&context));
1049        assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(-1, 100000).to_strings(&context));
1050        assert_eq!((String::from("0"), String::from(".000"), None, None), create_value(-1, 10000).to_strings(&context));
1051        assert_eq!((String::from("-0"), String::from(".001"), None, None), create_value(-1, 1000).to_strings(&context));
1052        assert_eq!((String::from("-0"), String::from(".010"), None, None), create_value(-1, 100).to_strings(&context));
1053        assert_eq!((String::from("-0"), String::from(".100"), None, None), create_value(-1, 10).to_strings(&context));
1054        assert_eq!((String::from("-0"), String::from(".499"), None, None), create_value(-49940, 100000).to_strings(&context));
1055        assert_eq!((String::from("-0"), String::from(".499"), None, None), create_value(-49949, 100000).to_strings(&context));
1056        assert_eq!((String::from("-0"), String::from(".500"), None, None), create_value(-49950, 100000).to_strings(&context));
1057        assert_eq!((String::from("-0"), String::from(".500"), None, None), create_value(-49951, 100000).to_strings(&context));
1058        assert_eq!((String::from("-0"), String::from(".900"), None, None), create_value(-9, 10).to_strings(&context));
1059        assert_eq!((String::from("-0"), String::from(".990"), None, None), create_value(-99, 100).to_strings(&context));
1060        assert_eq!((String::from("-0"), String::from(".999"), None, None), create_value(-999, 1000).to_strings(&context));
1061        assert_eq!((String::from("-1"), String::from(".000"), None, None), create_value(-9999, 10000).to_strings(&context));
1062        assert_eq!((String::from("-1"), String::from(".000"), None, None), create_value(-99999, 100000).to_strings(&context));
1063    }
1064
1065    #[test]
1066    fn test_recurring_is_formatted_with_precision() {
1067        let value = create_value(1, 3);
1068        let format = |dp: Option<u8>| {
1069            let context = Context::new().with_dp(dp);
1070            let (_, fraction, _, _) = value.to_strings(&context);
1071            return fraction;
1072        };
1073        assert_eq!(String::from(""), format(Some(0)));
1074        assert_eq!(String::from(".333333"), format(Some(6)));
1075        assert_eq!(String::from(".(3)"), format(None));
1076    }
1077
1078    #[test]
1079    fn test_hexadecimal_is_formatted_with_default() {
1080        let context = Context::new().with_format(Format::Base16(3));
1081        assert_eq!((String::from("0x000000000000000000000000"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
1082        assert_eq!((String::from("0x000000000000000000000001"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
1083        assert_eq!((String::from("0x00000000000000007ffffffe"), String::from(""), None, None), create_value(2147483646, 1).to_strings(&context));
1084        assert_eq!((String::from("0x00000000000000007fffffff"), String::from(""), None, None), create_value(2147483647, 1).to_strings(&context));
1085        assert_eq!((String::from("0x000000000000000080000000"), String::from(""), None, None), create_value(2147483648, 1).to_strings(&context));
1086        assert_eq!((String::from("0x000000000000000080000001"), String::from(""), None, None), create_value(2147483649, 1).to_strings(&context));
1087        assert_eq!((String::from("0x0000000000000000fffffffe"), String::from(""), None, None), create_value(4294967294, 1).to_strings(&context));
1088        assert_eq!((String::from("0x0000000000000000ffffffff"), String::from(""), None, None), create_value(4294967295, 1).to_strings(&context));
1089        assert_eq!((String::from("0x000000000000000100000000"), String::from(""), None, None), create_value(4294967296, 1).to_strings(&context));
1090        assert_eq!((String::from("0x000000000000000100000001"), String::from(""), None, None), create_value(4294967297, 1).to_strings(&context));
1091        assert_eq!((String::from("0x000000007ffffffffffffffe"), String::from(""), None, None), create_value(9223372036854775806, 1).to_strings(&context));
1092        assert_eq!((String::from("0x000000007fffffffffffffff"), String::from(""), None, None), create_value(9223372036854775807, 1).to_strings(&context));
1093        assert_eq!((String::from("0x000000008000000000000000"), String::from(""), None, None), create_value(9223372036854775808, 1).to_strings(&context));
1094        assert_eq!((String::from("0x000000008000000000000001"), String::from(""), None, None), create_value(9223372036854775809, 1).to_strings(&context));
1095        assert_eq!((String::from("0x00000000fffffffffffffffe"), String::from(""), None, None), create_value(18446744073709551614, 1).to_strings(&context));
1096        assert_eq!((String::from("0x00000000ffffffffffffffff"), String::from(""), None, None), create_value(18446744073709551615, 1).to_strings(&context));
1097        assert_eq!((String::from("0x000000010000000000000000"), String::from(""), None, None), create_value(18446744073709551616, 1).to_strings(&context));
1098        assert_eq!((String::from("0x000000010000000000000001"), String::from(""), None, None), create_value(18446744073709551617, 1).to_strings(&context));
1099        assert_eq!((String::from("0xffffffff0000000000000000"), String::from(""), None, None), create_value(-18446744073709551616, 1).to_strings(&context));
1100        assert_eq!((String::from("0xffffffff0000000000000001"), String::from(""), None, None), create_value(-18446744073709551615, 1).to_strings(&context));
1101        assert_eq!((String::from("0xffffffff8000000000000000"), String::from(""), None, None), create_value(-9223372036854775808, 1).to_strings(&context));
1102        assert_eq!((String::from("0xffffffff8000000000000001"), String::from(""), None, None), create_value(-9223372036854775807, 1).to_strings(&context));
1103        assert_eq!((String::from("0xffffffffffffffff00000000"), String::from(""), None, None), create_value(-4294967296, 1).to_strings(&context));
1104        assert_eq!((String::from("0xffffffffffffffff00000001"), String::from(""), None, None), create_value(-4294967295, 1).to_strings(&context));
1105        assert_eq!((String::from("0xffffffffffffffff80000000"), String::from(""), None, None), create_value(-2147483648, 1).to_strings(&context));
1106        assert_eq!((String::from("0xffffffffffffffff80000001"), String::from(""), None, None), create_value(-2147483647, 1).to_strings(&context));
1107        assert_eq!((String::from("0xfffffffffffffffffffffffe"), String::from(""), None, None), create_value(-2, 1).to_strings(&context));
1108        assert_eq!((String::from("0xffffffffffffffffffffffff"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
1109    }
1110
1111    #[test]
1112    fn test_hexadecimal_is_formatted_with_separator() {
1113        let context = Context::new().with_format(Format::Base16(3)).with_sep(true);
1114        assert_eq!((String::from("0x,00000000,00000000,00000000"), String::from(""), None, None), create_value(0, 1).to_strings(&context));
1115        assert_eq!((String::from("0x,00000000,00000000,00000001"), String::from(""), None, None), create_value(1, 1).to_strings(&context));
1116        assert_eq!((String::from("0x,00000000,00000000,7ffffffe"), String::from(""), None, None), create_value(2147483646, 1).to_strings(&context));
1117        assert_eq!((String::from("0x,00000000,00000000,7fffffff"), String::from(""), None, None), create_value(2147483647, 1).to_strings(&context));
1118        assert_eq!((String::from("0x,00000000,00000000,80000000"), String::from(""), None, None), create_value(2147483648, 1).to_strings(&context));
1119        assert_eq!((String::from("0x,00000000,00000000,80000001"), String::from(""), None, None), create_value(2147483649, 1).to_strings(&context));
1120        assert_eq!((String::from("0x,00000000,00000000,fffffffe"), String::from(""), None, None), create_value(4294967294, 1).to_strings(&context));
1121        assert_eq!((String::from("0x,00000000,00000000,ffffffff"), String::from(""), None, None), create_value(4294967295, 1).to_strings(&context));
1122        assert_eq!((String::from("0x,00000000,00000001,00000000"), String::from(""), None, None), create_value(4294967296, 1).to_strings(&context));
1123        assert_eq!((String::from("0x,00000000,00000001,00000001"), String::from(""), None, None), create_value(4294967297, 1).to_strings(&context));
1124        assert_eq!((String::from("0x,00000000,7fffffff,fffffffe"), String::from(""), None, None), create_value(9223372036854775806, 1).to_strings(&context));
1125        assert_eq!((String::from("0x,00000000,7fffffff,ffffffff"), String::from(""), None, None), create_value(9223372036854775807, 1).to_strings(&context));
1126        assert_eq!((String::from("0x,00000000,80000000,00000000"), String::from(""), None, None), create_value(9223372036854775808, 1).to_strings(&context));
1127        assert_eq!((String::from("0x,00000000,80000000,00000001"), String::from(""), None, None), create_value(9223372036854775809, 1).to_strings(&context));
1128        assert_eq!((String::from("0x,00000000,ffffffff,fffffffe"), String::from(""), None, None), create_value(18446744073709551614, 1).to_strings(&context));
1129        assert_eq!((String::from("0x,00000000,ffffffff,ffffffff"), String::from(""), None, None), create_value(18446744073709551615, 1).to_strings(&context));
1130        assert_eq!((String::from("0x,00000001,00000000,00000000"), String::from(""), None, None), create_value(18446744073709551616, 1).to_strings(&context));
1131        assert_eq!((String::from("0x,00000001,00000000,00000001"), String::from(""), None, None), create_value(18446744073709551617, 1).to_strings(&context));
1132        assert_eq!((String::from("0x,ffffffff,00000000,00000000"), String::from(""), None, None), create_value(-18446744073709551616, 1).to_strings(&context));
1133        assert_eq!((String::from("0x,ffffffff,00000000,00000001"), String::from(""), None, None), create_value(-18446744073709551615, 1).to_strings(&context));
1134        assert_eq!((String::from("0x,ffffffff,80000000,00000000"), String::from(""), None, None), create_value(-9223372036854775808, 1).to_strings(&context));
1135        assert_eq!((String::from("0x,ffffffff,80000000,00000001"), String::from(""), None, None), create_value(-9223372036854775807, 1).to_strings(&context));
1136        assert_eq!((String::from("0x,ffffffff,ffffffff,00000000"), String::from(""), None, None), create_value(-4294967296, 1).to_strings(&context));
1137        assert_eq!((String::from("0x,ffffffff,ffffffff,00000001"), String::from(""), None, None), create_value(-4294967295, 1).to_strings(&context));
1138        assert_eq!((String::from("0x,ffffffff,ffffffff,80000000"), String::from(""), None, None), create_value(-2147483648, 1).to_strings(&context));
1139        assert_eq!((String::from("0x,ffffffff,ffffffff,80000001"), String::from(""), None, None), create_value(-2147483647, 1).to_strings(&context));
1140        assert_eq!((String::from("0x,ffffffff,ffffffff,fffffffe"), String::from(""), None, None), create_value(-2, 1).to_strings(&context));
1141        assert_eq!((String::from("0x,ffffffff,ffffffff,ffffffff"), String::from(""), None, None), create_value(-1, 1).to_strings(&context));
1142    }
1143
1144    #[test]
1145    fn test_hexadecimal_is_measured_from_valid() {
1146        assert_eq!(1, create_value(0, 1).measure_hexadecimal()); // "00000000"
1147        assert_eq!(1, create_value(1, 1).measure_hexadecimal()); // "00000001"
1148        assert_eq!(1, create_value(2147483646, 1).measure_hexadecimal()); // "7ffffffe"
1149        assert_eq!(1, create_value(2147483647, 1).measure_hexadecimal()); // "7fffffff"
1150        assert_eq!(2, create_value(2147483648, 1).measure_hexadecimal()); // "00000000 80000000"
1151        assert_eq!(2, create_value(2147483649, 1).measure_hexadecimal()); // "00000000 80000001"
1152        assert_eq!(2, create_value(4294967294, 1).measure_hexadecimal()); // "00000000 fffffffe"
1153        assert_eq!(2, create_value(4294967295, 1).measure_hexadecimal()); // "00000000 ffffffff"
1154        assert_eq!(2, create_value(4294967296, 1).measure_hexadecimal()); // "00000001 00000000"
1155        assert_eq!(2, create_value(4294967297, 1).measure_hexadecimal()); // "00000001 00000001"
1156        assert_eq!(2, create_value(9223372036854775806, 1).measure_hexadecimal()); // "7fffffff fffffffe"
1157        assert_eq!(2, create_value(9223372036854775807, 1).measure_hexadecimal()); // "7fffffff ffffffff"
1158        assert_eq!(3, create_value(9223372036854775808, 1).measure_hexadecimal()); // "00000000 80000000 00000000"
1159        assert_eq!(3, create_value(9223372036854775809, 1).measure_hexadecimal()); // "00000000 80000000 00000001"
1160        assert_eq!(3, create_value(18446744073709551614, 1).measure_hexadecimal()); // "00000000 ffffffff fffffffe"
1161        assert_eq!(3, create_value(18446744073709551615, 1).measure_hexadecimal()); // "00000000 ffffffff ffffffff"
1162        assert_eq!(3, create_value(18446744073709551616, 1).measure_hexadecimal()); // "00000001 00000000 00000000"
1163        assert_eq!(3, create_value(18446744073709551617, 1).measure_hexadecimal()); // "00000001 00000000 00000001"
1164        assert_eq!(3, create_value(-18446744073709551616, 1).measure_hexadecimal()); // "ffffffff 00000000 00000000"
1165        assert_eq!(3, create_value(-18446744073709551615, 1).measure_hexadecimal()); // "ffffffff 00000000 00000001"
1166        assert_eq!(2, create_value(-9223372036854775808, 1).measure_hexadecimal()); // "80000000 00000000"
1167        assert_eq!(2, create_value(-9223372036854775807, 1).measure_hexadecimal()); // "80000000 00000001"
1168        assert_eq!(2, create_value(-4294967296, 1).measure_hexadecimal()); // "ffffffff 00000000"
1169        assert_eq!(2, create_value(-4294967295, 1).measure_hexadecimal()); // "ffffffff 00000001"
1170        assert_eq!(1, create_value(-2147483648, 1).measure_hexadecimal()); // "80000000"
1171        assert_eq!(1, create_value(-2147483647, 1).measure_hexadecimal()); // "80000001"
1172        assert_eq!(1, create_value(-2, 1).measure_hexadecimal()); // "fffffffe"
1173        assert_eq!(1, create_value(-1, 1).measure_hexadecimal()); // "ffffffff"
1174    }
1175
1176    #[test]
1177    fn test_time_is_formatted_without_separator() {
1178        let context = Context::new().with_sep(true).with_dp(Some(6));
1179        assert_time("2024-06-30T12:00:00", ".000Z", create_value(1719748800000, 1000), &context);
1180        assert_time("2024-06-30T12:00:00", ".987Z", create_value(1719748800987, 1000), &context);
1181        assert_time("2024-12-31T12:00:00", ".000Z", create_value(1735646400000, 1000), &context);
1182        assert_time("2024-12-31T12:00:00", ".987Z", create_value(1735646400987, 1000), &context);
1183    }
1184
1185    #[test]
1186    fn test_delta_is_formatted_without_separator() {
1187        let context = Context::new().with_sep(true).with_dp(Some(6));
1188        assert_delta("00", ".000", create_value(0, 1), &context);
1189        assert_delta("59", ".999", create_value(59999, 1000), &context);
1190        assert_delta("01:00", ".000", create_value(60000, 1000), &context);
1191        assert_delta("59:59", ".999", create_value(3599999, 1000), &context);
1192        assert_delta("01:00:00", ".000", create_value(3600000, 1000), &context);
1193        assert_delta("23:59:59", ".999", create_value(86399999, 1000), &context);
1194        assert_delta("1T00:00:00", ".000", create_value(86400000, 1000), &context);
1195        assert_delta("100T00:00:00", ".000", create_value(8640000000, 1000), &context);
1196        assert_delta("-59", ".999", create_value(-59999, 1000), &context);
1197        assert_delta("-01:00", ".000", create_value(-60000, 1000), &context);
1198        assert_delta("-59:59", ".999", create_value(-3599999, 1000), &context);
1199        assert_delta("-01:00:00", ".000", create_value(-3600000, 1000), &context);
1200        assert_delta("-23:59:59", ".999", create_value(-86399999, 1000), &context);
1201        assert_delta("-1T00:00:00", ".000", create_value(-86400000, 1000), &context);
1202        assert_delta("-100T00:00:00", ".000", create_value(-8640000000, 1000), &context);
1203    }
1204
1205    fn assert_time(integer: &str, fraction: &str, value: Value, context: &Context) {
1206        let expected = (String::from(integer), String::from(fraction), None, None);
1207        let actual = value.with_meaning(Meaning::Time).to_strings(context);
1208        assert_eq!(expected, actual);
1209    }
1210
1211    fn assert_delta(integer: &str, fraction: &str, value: Value, context: &Context) {
1212        let expected = (String::from(integer), String::from(fraction), None, None);
1213        let actual = value.with_meaning(Meaning::Delta).to_strings(context);
1214        assert_eq!(expected, actual);
1215    }
1216
1217    #[test]
1218    fn test_decimal_is_formatted_from_nan() {
1219        let expected = (String::from("NaN"), String::from(""), None, None);
1220        let context = Context::new();
1221        let actual = VALUE_NAN.to_strings(&context);
1222        assert_eq!(expected, actual);
1223    }
1224
1225    #[test]
1226    fn test_hexadecimal_is_measured_from_nan() {
1227        assert_eq!(1, VALUE_NAN.measure_hexadecimal());
1228    }
1229
1230    //       | Plain Delta Time
1231    // ------+------------------
1232    // Plain | Plain Delta Time
1233    // Delta | Delta Delta Time
1234    // Time  | Time  Time    -
1235
1236    #[test]
1237    fn test_plain_values_are_added_by_value() {
1238        assert_eq!(Value::calc_add(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(8, 1)));
1239        assert_eq!(Value::calc_add(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1240        assert_eq!(Value::calc_add(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1241        assert_eq!(Value::calc_add(create_nan(), create_nan()).ok(), Some(create_nan()));
1242    }
1243
1244    #[test]
1245    fn test_plain_values_are_added_by_meaning() {
1246        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1247        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Plain, Meaning::Delta), Some(Meaning::Delta));
1248        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Plain, Meaning::Time), Some(Meaning::Time));
1249        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1250        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Delta, Meaning::Delta), Some(Meaning::Delta));
1251        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Delta, Meaning::Time), Some(Meaning::Time));
1252        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Time, Meaning::Plain), Some(Meaning::Time));
1253        assert_eq!(perform_binary_ok(Value::calc_add, Meaning::Time, Meaning::Delta), Some(Meaning::Time));
1254        assert_eq!(perform_binary_err(Value::calc_add, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1255    }
1256
1257    //       | Plain Delta Time
1258    // ------+------------------
1259    // Plain | Plain Delta   -
1260    // Delta | Delta Delta   -
1261    // Time  | Time  Time  Delta
1262
1263    #[test]
1264    fn test_plain_values_are_subtracted_by_value() {
1265        assert_eq!(Value::calc_sub(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(3, 1)));
1266        assert_eq!(Value::calc_sub(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1267        assert_eq!(Value::calc_sub(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1268        assert_eq!(Value::calc_sub(create_nan(), create_nan()).ok(), Some(create_nan()));
1269    }
1270
1271    #[test]
1272    fn test_plain_values_are_subtracted_by_meaning() {
1273        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1274        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Plain, Meaning::Delta), Some(Meaning::Delta));
1275        assert_eq!(perform_binary_err(Value::calc_sub, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1276        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1277        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Delta, Meaning::Delta), Some(Meaning::Delta));
1278        assert_eq!(perform_binary_err(Value::calc_sub, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1279        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Time, Meaning::Plain), Some(Meaning::Time));
1280        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Time, Meaning::Delta), Some(Meaning::Time));
1281        assert_eq!(perform_binary_ok(Value::calc_sub, Meaning::Time, Meaning::Time), Some(Meaning::Delta));
1282    }
1283
1284    //       | Plain Delta Time
1285    // ------+------------------
1286    // Plain | Plain Delta   -
1287    // Delta | Delta   -     -
1288    // Time  |   -     -     -
1289
1290    #[test]
1291    fn test_plain_values_are_multiplied_by_value() {
1292        assert_eq!(Value::calc_mul(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(1375, 100)));
1293        assert_eq!(Value::calc_mul(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1294        assert_eq!(Value::calc_mul(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1295        assert_eq!(Value::calc_mul(create_nan(), create_nan()).ok(), Some(create_nan()));
1296    }
1297
1298    #[test]
1299    fn test_plain_values_are_multiplied_by_meaning() {
1300        assert_eq!(perform_binary_ok(Value::calc_mul, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1301        assert_eq!(perform_binary_ok(Value::calc_mul, Meaning::Plain, Meaning::Delta), Some(Meaning::Delta));
1302        assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1303        assert_eq!(perform_binary_ok(Value::calc_mul, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1304        assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1305        assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1306        assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1307        assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1308        assert_eq!(perform_binary_err(Value::calc_mul, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1309    }
1310
1311    //       | Plain Delta Time
1312    // ------+------------------
1313    // Plain | Plain   -     -
1314    // Delta | Delta   -     -
1315    // Time  |   -     -     -
1316
1317    #[test]
1318    fn test_plain_values_are_divided_by_value() {
1319        assert_eq!(Value::calc_div(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(22, 10)));
1320        assert_eq!(Value::calc_div(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1321        assert_eq!(Value::calc_div(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1322        assert_eq!(Value::calc_div(create_nan(), create_nan()).ok(), Some(create_nan()));
1323    }
1324
1325    #[test]
1326    fn test_plain_values_are_divided_by_zero() {
1327        assert_eq!(Value::calc_div(create_ref(55, 10), create_ref(0, 1)).ok(), Some(create_nan()));
1328        assert_eq!(Value::calc_div(create_nan(), create_ref(0, 1)).ok(), Some(create_nan()));
1329    }
1330
1331    #[test]
1332    fn test_plain_values_are_divided_by_meaning() {
1333        assert_eq!(perform_binary_ok(Value::calc_div, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1334        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1335        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1336        assert_eq!(perform_binary_ok(Value::calc_div, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1337        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1338        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1339        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1340        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1341        assert_eq!(perform_binary_err(Value::calc_div, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1342    }
1343
1344    #[test]
1345    fn test_plain_values_are_remaindered_by_value() {
1346        assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(25, 10)).ok(), Some(create_ref(5, 10)));
1347        assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(-25, 10)).ok(), Some(create_ref(5, 10)));
1348        assert_eq!(Value::calc_mod(create_ref(-55, 10), create_ref(25, 10)).ok(), Some(create_ref(-5, 10)));
1349        assert_eq!(Value::calc_mod(create_ref(-55, 10), create_ref(-25, 10)).ok(), Some(create_ref(-5, 10)));
1350        assert_eq!(Value::calc_mod(create_ref(55, 10), create_nan()).ok(), Some(create_nan()));
1351        assert_eq!(Value::calc_mod(create_ref(-55, 10), create_nan()).ok(), Some(create_nan()));
1352        assert_eq!(Value::calc_mod(create_nan(), create_ref(25, 10)).ok(), Some(create_nan()));
1353        assert_eq!(Value::calc_mod(create_nan(), create_ref(-25, 10)).ok(), Some(create_nan()));
1354        assert_eq!(Value::calc_mod(create_nan(), create_nan()).ok(), Some(create_nan()));
1355    }
1356
1357    #[test]
1358    fn test_plain_values_are_remaindered_by_zero() {
1359        assert_eq!(Value::calc_mod(create_ref(55, 10), create_ref(0, 1)).ok(), Some(create_nan()));
1360        assert_eq!(Value::calc_mod(create_nan(), create_ref(0, 1)).ok(), Some(create_nan()));
1361    }
1362
1363    #[test]
1364    fn test_plain_values_are_remaindered_by_meaning() {
1365        assert_eq!(perform_binary_ok(Value::calc_mod, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1366        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1367        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1368        assert_eq!(perform_binary_ok(Value::calc_mod, Meaning::Delta, Meaning::Plain), Some(Meaning::Delta));
1369        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1370        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1371        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1372        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1373        assert_eq!(perform_binary_err(Value::calc_mod, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1374    }
1375
1376    // Plain | Plain
1377    // Delta | Delta
1378    // Time  |   -
1379
1380    #[test]
1381    fn test_plain_values_are_negated_by_value() {
1382        assert_eq!(Value::calc_neg(create_ref(5, 10)).ok(), Some(create_ref(-5, 10)));
1383        assert_eq!(Value::calc_neg(create_ref(-5, 10)).ok(), Some(create_ref(5, 10)));
1384        assert_eq!(Value::calc_neg(create_nan()).ok(), Some(create_nan()));
1385    }
1386
1387    #[test]
1388    fn test_plain_values_are_negated_by_meaning() {
1389        assert_eq!(perform_unary_ok(Value::calc_neg, Meaning::Plain), Some(Meaning::Plain));
1390        assert_eq!(perform_unary_ok(Value::calc_neg, Meaning::Delta), Some(Meaning::Delta));
1391        assert_eq!(perform_unary_err(Value::calc_neg, Meaning::Time), Some(EngineError::BadTimeOp));
1392    }
1393
1394    // Plain | Plain
1395    // Delta |   -
1396    // Time  |   -
1397
1398    #[test]
1399    fn test_plain_values_are_inverted_if_valid() {
1400        assert_eq!(Value::calc_inv(create_ref(5, 10)).ok(), Some(create_ref(10, 5)));
1401        assert_eq!(Value::calc_inv(create_ref(-5, 10)).ok(), Some(create_ref(-10, 5)));
1402        assert_eq!(Value::calc_inv(create_nan()).ok(), Some(create_nan()));
1403    }
1404
1405    #[test]
1406    fn test_plain_values_are_inverted_if_zero() {
1407        assert_eq!(Value::calc_inv(create_ref(0, 1)).ok(), Some(create_nan()));
1408    }
1409
1410    #[test]
1411    fn test_plain_values_are_inverted_by_meaning() {
1412        assert_eq!(perform_unary_ok(Value::calc_inv, Meaning::Plain), Some(Meaning::Plain));
1413        assert_eq!(perform_unary_err(Value::calc_inv, Meaning::Delta), Some(EngineError::BadTimeOp));
1414        assert_eq!(perform_unary_err(Value::calc_inv, Meaning::Time), Some(EngineError::BadTimeOp));
1415    }
1416
1417    //       | Plain Delta Time
1418    // ------+------------------
1419    // Plain | Plain   -     -
1420    // Delta |   -     -     -
1421    // Time  |   -     -     -
1422
1423    #[test]
1424    fn test_plain_values_are_raised_to_integer_power() {
1425        assert_eq!(Value::calc_pow(create_ref(3, 1), create_ref(4, 1)).ok(), Some(create_ref(81, 1)));
1426        assert_eq!(Value::calc_pow(create_ref(3, 1), create_nan()).ok(), Some(create_nan()));
1427        assert_eq!(Value::calc_pow(create_nan(), create_ref(4, 1)).ok(), Some(create_nan()));
1428        assert_eq!(Value::calc_pow(create_nan(), create_nan()).ok(), Some(create_nan()));
1429    }
1430
1431    #[test]
1432    fn test_plain_values_are_raised_to_fractional_power() {
1433        assert_eq!(Value::calc_pow(create_ref(3, 1), create_nan()).ok(), Some(create_nan()));
1434        assert_eq!(Value::calc_pow(create_nan(), create_ref(1, 2)).ok(), Some(create_nan()));
1435        assert_eq!(Value::calc_pow(create_nan(), create_nan()).ok(), Some(create_nan()));
1436    }
1437
1438    #[test]
1439    fn test_plain_values_are_raised_by_meaning() {
1440        assert_eq!(perform_binary_ok(Value::calc_pow, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1441        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1442        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1443        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1444        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1445        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1446        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1447        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1448        assert_eq!(perform_binary_err(Value::calc_pow, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1449    }
1450
1451    // Plain | Plain
1452    // Delta |   -
1453    // Time  |   -
1454
1455    #[test]
1456    fn test_plain_values_have_square_root_if_positive() {
1457        assert_eq!(Value::calc_sqrt(create_nan()).ok(), Some(create_nan()));
1458    }
1459
1460    #[test]
1461    fn test_plain_values_have_square_root_if_negative() {
1462        assert_eq!(Value::calc_sqrt(create_ref(-3, 1)).ok(), Some(create_nan()));
1463    }
1464
1465    #[test]
1466    fn test_plain_values_have_square_root_by_meaning() {
1467        assert_eq!(perform_unary_ok(Value::calc_sqrt, Meaning::Plain), Some(Meaning::Plain));
1468        assert_eq!(perform_unary_err(Value::calc_sqrt, Meaning::Delta), Some(EngineError::BadTimeOp));
1469        assert_eq!(perform_unary_err(Value::calc_sqrt, Meaning::Time), Some(EngineError::BadTimeOp));
1470    }
1471
1472    #[test]
1473    fn test_plain_values_are_summed() {
1474        assert_eq!(Some(create_ref(0, 1)), Value::calc_sum(vec![]).ok());
1475        assert_eq!(Some(create_ref(0, 1)), Value::calc_sum(vec![create_nan(), create_nan(), create_nan()]).ok());
1476        assert_eq!(Some(create_ref(25, 10)), Value::calc_sum(vec![create_ref(25, 10), create_nan(), create_nan()]).ok());
1477        assert_eq!(Some(create_ref(65, 10)), Value::calc_sum(vec![create_ref(25, 10), create_ref(4, 1), create_nan()]).ok());
1478        assert_eq!(Some(create_ref(120, 10)), Value::calc_sum(vec![create_ref(25, 10), create_ref(4, 1), create_ref(55, 10)]).ok());
1479    }
1480
1481    #[test]
1482    fn test_plain_values_are_producted() {
1483        assert_eq!(Some(create_ref(1, 1)), Value::calc_prod(vec![]).ok());
1484        assert_eq!(Some(create_ref(1, 1)), Value::calc_prod(vec![create_nan(), create_nan(), create_nan()]).ok());
1485        assert_eq!(Some(create_ref(25, 10)), Value::calc_prod(vec![create_ref(25, 10), create_nan(), create_nan()]).ok());
1486        assert_eq!(Some(create_ref(100, 10)), Value::calc_prod(vec![create_ref(25, 10), create_ref(4, 1), create_nan()]).ok());
1487        assert_eq!(Some(create_ref(550, 10)), Value::calc_prod(vec![create_ref(25, 10), create_ref(4, 1), create_ref(55, 10)]).ok());
1488    }
1489
1490    //       | Plain Delta Time
1491    // ------+------------------
1492    // Plain | Plain   -     -
1493    // Delta |   -     -     -
1494    // Time  |   -     -     -
1495
1496    #[test]
1497    fn test_plain_values_have_bitwise_and_by_value() {
1498        assert_eq!(Value::calc_and(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0xf000, 1)));
1499        assert_eq!(Value::calc_and(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1500        assert_eq!(Value::calc_and(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1501        assert_eq!(Value::calc_and(create_nan(), create_nan()).ok(), Some(create_nan()));
1502    }
1503
1504    #[test]
1505    fn test_plain_values_have_bitwise_and_by_meaning() {
1506        assert_eq!(perform_binary_ok(Value::calc_and, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1507        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1508        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1509        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1510        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1511        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1512        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1513        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1514        assert_eq!(perform_binary_err(Value::calc_and, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1515    }
1516
1517    #[test]
1518    fn test_plain_values_have_bitwise_or_by_value() {
1519        assert_eq!(Value::calc_or(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0xfff0, 1)));
1520        assert_eq!(Value::calc_or(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1521        assert_eq!(Value::calc_or(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1522        assert_eq!(Value::calc_or(create_nan(), create_nan()).ok(), Some(create_nan()));
1523    }
1524
1525    #[test]
1526    fn test_plain_values_have_bitwise_or_by_meaning() {
1527        assert_eq!(perform_binary_ok(Value::calc_or, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1528        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1529        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1530        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1531        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1532        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1533        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1534        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1535        assert_eq!(perform_binary_err(Value::calc_or, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1536    }
1537
1538    #[test]
1539    fn test_plain_values_have_bitwise_xor_by_value() {
1540        assert_eq!(Value::calc_xor(create_ref(0xff00, 1), create_ref(0xf0f0, 1)).ok(), Some(create_ref(0x0ff0, 1)));
1541        assert_eq!(Value::calc_xor(create_ref(0xff00, 1), create_nan()).ok(), Some(create_nan()));
1542        assert_eq!(Value::calc_xor(create_nan(), create_ref(0xf0f0, 1)).ok(), Some(create_nan()));
1543        assert_eq!(Value::calc_xor(create_nan(), create_nan()).ok(), Some(create_nan()));
1544    }
1545
1546    #[test]
1547    fn test_plain_values_have_bitwise_xor_by_meaning() {
1548        assert_eq!(perform_binary_ok(Value::calc_xor, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1549        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1550        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1551        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1552        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1553        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1554        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1555        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1556        assert_eq!(perform_binary_err(Value::calc_xor, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1557    }
1558
1559    #[test]
1560    fn test_plain_values_are_shifted_left_by_value() {
1561        assert_eq!(Value::calc_shl(create_ref(35, 10), create_ref(29, 10)).ok(), Some(create_ref(14, 1)));
1562        assert_eq!(Value::calc_shl(create_ref(-35, 10), create_ref(29, 10)).ok(), Some(create_ref(-14, 1)));
1563        assert_eq!(Value::calc_shl(create_ref(35, 10), create_ref(-29, 10)).ok(), Some(create_ref(875, 1000)));
1564        assert_eq!(Value::calc_shl(create_ref(-35, 10), create_ref(-29, 10)).ok(), Some(create_ref(-875, 1000)));
1565        assert_eq!(Value::calc_shl(create_ref(35, 10), create_nan()).ok(), Some(create_nan()));
1566        assert_eq!(Value::calc_shl(create_ref(-35, 10), create_nan()).ok(), Some(create_nan()));
1567        assert_eq!(Value::calc_shl(create_nan(), create_ref(29, 10)).ok(), Some(create_nan()));
1568        assert_eq!(Value::calc_shl(create_nan(), create_ref(-29, 10)).ok(), Some(create_nan()));
1569        assert_eq!(Value::calc_shl(create_nan(), create_nan()).ok(), Some(create_nan()));
1570    }
1571
1572    #[test]
1573    fn test_plain_values_are_shifted_left_by_meaning() {
1574        assert_eq!(perform_binary_ok(Value::calc_shl, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1575        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1576        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1577        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1578        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1579        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1580        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1581        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1582        assert_eq!(perform_binary_err(Value::calc_shl, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1583    }
1584
1585    #[test]
1586    fn test_plain_values_are_shifted_right_by_value() {
1587        assert_eq!(Value::calc_shr(create_ref(35, 10), create_ref(29, 10)).ok(), Some(create_ref(875, 1000)));
1588        assert_eq!(Value::calc_shr(create_ref(-35, 10), create_ref(29, 10)).ok(), Some(create_ref(-875, 1000)));
1589        assert_eq!(Value::calc_shr(create_ref(35, 10), create_ref(-29, 10)).ok(), Some(create_ref(14, 1)));
1590        assert_eq!(Value::calc_shr(create_ref(-35, 10), create_ref(-29, 10)).ok(), Some(create_ref(-14, 1)));
1591        assert_eq!(Value::calc_shr(create_ref(35, 10), create_nan()).ok(), Some(create_nan()));
1592        assert_eq!(Value::calc_shr(create_ref(-35, 10), create_nan()).ok(), Some(create_nan()));
1593        assert_eq!(Value::calc_shr(create_nan(), create_ref(29, 10)).ok(), Some(create_nan()));
1594        assert_eq!(Value::calc_shr(create_nan(), create_ref(-29, 10)).ok(), Some(create_nan()));
1595        assert_eq!(Value::calc_shr(create_nan(), create_nan()).ok(), Some(create_nan()));
1596    }
1597
1598    #[test]
1599    fn test_plain_values_are_shifted_right_by_meaning() {
1600        assert_eq!(perform_binary_ok(Value::calc_shr, Meaning::Plain, Meaning::Plain), Some(Meaning::Plain));
1601        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Plain, Meaning::Delta), Some(EngineError::BadTimeOp));
1602        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Plain, Meaning::Time), Some(EngineError::BadTimeOp));
1603        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Delta, Meaning::Plain), Some(EngineError::BadTimeOp));
1604        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Delta, Meaning::Delta), Some(EngineError::BadTimeOp));
1605        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Delta, Meaning::Time), Some(EngineError::BadTimeOp));
1606        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Time, Meaning::Plain), Some(EngineError::BadTimeOp));
1607        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Time, Meaning::Delta), Some(EngineError::BadTimeOp));
1608        assert_eq!(perform_binary_err(Value::calc_shr, Meaning::Time, Meaning::Time), Some(EngineError::BadTimeOp));
1609    }
1610
1611    fn perform_unary_ok(
1612        function: fn(ValueRef) -> MyResult<ValueRef>,
1613        meaning: Meaning,
1614    ) -> Option<Meaning> {
1615        let value = create_value(1, 1).with_meaning(meaning);
1616        let value = Rc::new(RefCell::new(value));
1617        let result = function(value);
1618        result.ok().map(get_meaning)
1619    }
1620
1621    fn perform_unary_err(
1622        function: fn(ValueRef) -> MyResult<ValueRef>,
1623        meaning: Meaning,
1624    ) -> Option<EngineError> {
1625        let value = create_value(1, 1).with_meaning(meaning);
1626        let value = Rc::new(RefCell::new(value));
1627        let result = function(value);
1628        result.err().and_then(filter_error)
1629    }
1630
1631    fn perform_binary_ok(
1632        function: fn(ValueRef, ValueRef) -> MyResult<ValueRef>,
1633        lhs: Meaning,
1634        rhs: Meaning,
1635    ) -> Option<Meaning> {
1636        let lhs = create_value(1, 1).with_meaning(lhs);
1637        let rhs = create_value(1, 1).with_meaning(rhs);
1638        let lhs = Rc::new(RefCell::new(lhs));
1639        let rhs = Rc::new(RefCell::new(rhs));
1640        let result = function(lhs, rhs);
1641        result.ok().map(get_meaning)
1642    }
1643
1644    fn perform_binary_err(
1645        function: fn(ValueRef, ValueRef) -> MyResult<ValueRef>,
1646        lhs: Meaning,
1647        rhs: Meaning,
1648    ) -> Option<EngineError> {
1649        let lhs = create_value(1, 1).with_meaning(lhs);
1650        let rhs = create_value(1, 1).with_meaning(rhs);
1651        let lhs = Rc::new(RefCell::new(lhs));
1652        let rhs = Rc::new(RefCell::new(rhs));
1653        let result = function(lhs, rhs);
1654        result.err().and_then(filter_error)
1655    }
1656
1657    fn get_meaning(value: ValueRef) -> Meaning {
1658        value.borrow().meaning
1659    }
1660
1661    fn filter_error(error: MyError) -> Option<EngineError> {
1662        match error {
1663            MyError::Engine(error) => Some(error),
1664            _ => None,
1665        }
1666    }
1667
1668    fn create_value(numer: i128, denom: i128) -> Value {
1669        let number = create_ratio(numer, denom);
1670        Value::new(Some(number))
1671    }
1672
1673    fn create_ref(numer: i128, denom: i128) -> ValueRef {
1674        let number = create_ratio(numer, denom);
1675        let value = Value::new(Some(number));
1676        Rc::new(RefCell::new(value))
1677    }
1678
1679    pub fn create_nan() -> ValueRef {
1680        let value = Value::new(None);
1681        Rc::new(RefCell::new(value))
1682    }
1683
1684    pub fn parse_string(number: &str) -> ValueRef {
1685        let regex = regex!(r#"^(\S+)(?: \[(delta|time)\])?(?: = (\w+))?(?: # (.+))?$"#);
1686        let captures = regex.captures(number).unwrap();
1687        let number = captures.get(1).as_ref().map(Match::as_str).unwrap();
1688        let mut value = Value::from_string(number).unwrap();
1689        match captures.get(2).as_ref().map(Match::as_str) {
1690            Some("delta") => value.set_meaning(Meaning::Delta),
1691            Some("time") => value.set_meaning(Meaning::Time),
1692            _ => value.set_meaning(Meaning::Plain),
1693        }
1694        if let Some(variable) = captures.get(3).as_ref().map(Match::as_str) {
1695            value.set_variable(variable);
1696        }
1697        if let Some(comment) = captures.get(4).as_ref().map(Match::as_str) {
1698            value.set_comment(comment);
1699        }
1700        Rc::new(RefCell::new(value))
1701    }
1702
1703    pub fn parse_strings(values: Vec<&str>) -> Vec<ValueRef> {
1704        values.iter().map(|x| parse_string(x)).collect()
1705    }
1706
1707    fn create_ratio(numer: i128, denom: i128) -> BigRational {
1708        let numer = BigInt::from(numer);
1709        let denom = BigInt::from(denom);
1710        BigRational::new(numer, denom)
1711    }
1712
1713    fn fudge_ratio(number: BigRational) -> Option<BigRational> {
1714        number.to_f64()
1715            .map(f64::sqrt)
1716            .and_then(BigRational::from_f64)
1717            .and_then(square_ratio)
1718    }
1719
1720    fn square_ratio(number: BigRational) -> Option<BigRational> {
1721        number.checked_mul(&number)
1722    }
1723
1724    fn opposite_ratio(number: BigRational) -> Option<BigRational> {
1725        create_ratio(2, 1).checked_mul(&number.round()).and_then(|x| x.checked_sub(&number))
1726    }
1727}