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
26impl 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 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" };
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 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 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 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 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 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 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 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 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 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); let number2 = fudge(ratio(16, 8)).and_then(opposite); let number3 = fudge(ratio(16, 8)); let number4 = fudge(ratio(17, 8)); 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)); let number2 = fudge(ratio(1088924, 99000)); let number3 = fudge(ratio(1997457, 999000)); let number4 = fudge(ratio(19995891, 9999000)); 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()); assert_eq!(1, value(1, 1).measure_hexadecimal()); assert_eq!(1, value(2147483646, 1).measure_hexadecimal()); assert_eq!(1, value(2147483647, 1).measure_hexadecimal()); assert_eq!(2, value(2147483648, 1).measure_hexadecimal()); assert_eq!(2, value(2147483649, 1).measure_hexadecimal()); assert_eq!(2, value(4294967294, 1).measure_hexadecimal()); assert_eq!(2, value(4294967295, 1).measure_hexadecimal()); assert_eq!(2, value(4294967296, 1).measure_hexadecimal()); assert_eq!(2, value(4294967297, 1).measure_hexadecimal()); assert_eq!(2, value(9223372036854775806, 1).measure_hexadecimal()); assert_eq!(2, value(9223372036854775807, 1).measure_hexadecimal()); assert_eq!(3, value(9223372036854775808, 1).measure_hexadecimal()); assert_eq!(3, value(9223372036854775809, 1).measure_hexadecimal()); assert_eq!(3, value(18446744073709551614, 1).measure_hexadecimal()); assert_eq!(3, value(18446744073709551615, 1).measure_hexadecimal()); assert_eq!(3, value(18446744073709551616, 1).measure_hexadecimal()); assert_eq!(3, value(18446744073709551617, 1).measure_hexadecimal()); assert_eq!(3, value(-18446744073709551616, 1).measure_hexadecimal()); assert_eq!(3, value(-18446744073709551615, 1).measure_hexadecimal()); assert_eq!(2, value(-9223372036854775808, 1).measure_hexadecimal()); assert_eq!(2, value(-9223372036854775807, 1).measure_hexadecimal()); assert_eq!(2, value(-4294967296, 1).measure_hexadecimal()); assert_eq!(2, value(-4294967295, 1).measure_hexadecimal()); assert_eq!(1, value(-2147483648, 1).measure_hexadecimal()); assert_eq!(1, value(-2147483647, 1).measure_hexadecimal()); assert_eq!(1, value(-2, 1).measure_hexadecimal()); assert_eq!(1, value(-1, 1).measure_hexadecimal()); }
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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}