rpn_cli/
value.rs

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