@@ -3,6 +3,7 @@ use std::num::FpCategory;
3
3
use util:: grisu2;
4
4
use util:: write:: write;
5
5
6
+ /// NaN value represented in `Number` type. NaN is equal to itself.
6
7
pub const NAN : Number = Number {
7
8
category : NAN_MASK ,
8
9
mantissa : 0 ,
@@ -13,14 +14,45 @@ const NEGATIVE: u8 = 0;
13
14
const POSITIVE : u8 = 1 ;
14
15
const NAN_MASK : u8 = !1 ;
15
16
17
+ /// Number representation used inside `JsonValue`. You can easily convert
18
+ /// the `Number` type into native Rust number types and back, or use the
19
+ /// equality operator with another number type.
20
+ ///
21
+ /// ```
22
+ /// # use json::number::Number;
23
+ /// let foo: Number = 3.14.into();
24
+ /// let bar: f64 = foo.into();
25
+ ///
26
+ /// assert_eq!(foo, 3.14);
27
+ /// assert_eq!(bar, 3.14);
28
+ /// ```
29
+ ///
30
+ /// More often than not you will deal with `JsonValue::Number` variant that
31
+ /// wraps around this type, instead of using the methods here directly.
16
32
#[ derive( Copy , Clone , Debug ) ]
17
33
pub struct Number {
34
+ // A byte describing the sign and NaN-ness of the number.
35
+ // category == 0 -> negative sign
36
+ // category == 1 -> positive sign
37
+ // category > 1 -> NaN
18
38
category : u8 ,
39
+
40
+ // Decimal exponent, analog to `e` notation in string form.
19
41
exponent : i16 ,
42
+
43
+ // Integer base before sing and exponent applied.
20
44
mantissa : u64 ,
21
45
}
22
46
23
47
impl Number {
48
+ /// Construct a new `Number` from parts. This can't create a NaN value.
49
+ ///
50
+ /// ```
51
+ /// # use json::number::Number;
52
+ /// let pi = Number::from_parts(true, 3141592653589793, -15);
53
+ ///
54
+ /// assert_eq!(pi, 3.141592653589793);
55
+ /// ```
24
56
#[ inline]
25
57
pub fn from_parts ( positive : bool , mantissa : u64 , exponent : i16 ) -> Self {
26
58
Number {
@@ -30,6 +62,17 @@ impl Number {
30
62
}
31
63
}
32
64
65
+ /// Reverse to `from_parts` - obtain parts from an existing `Number`.
66
+ ///
67
+ /// ```
68
+ /// # use json::number::Number;
69
+ /// let pi = Number::from(3.141592653589793);
70
+ /// let (positive, mantissa, exponent) = pi.as_parts();
71
+ ///
72
+ /// assert_eq!(positive, true);
73
+ /// assert_eq!(mantissa, 3141592653589793);
74
+ /// assert_eq!(exponent, -15);
75
+ /// ```
33
76
#[ inline]
34
77
pub fn as_parts ( & self ) -> ( bool , u64 , i16 ) {
35
78
( self . category == POSITIVE , self . mantissa , self . exponent )
@@ -50,11 +93,28 @@ impl Number {
50
93
self . category & NAN_MASK != 0
51
94
}
52
95
96
+ /// Test if the number is NaN or has a zero value.
53
97
#[ inline]
54
98
pub fn is_empty ( & self ) -> bool {
55
99
self . mantissa == 0 || self . is_nan ( )
56
100
}
57
101
102
+ /// Obtain an integer at a fixed decimal point. This is useful for
103
+ /// converting monetary values and doing arithmetic on them without
104
+ /// rounding errors introduced by floating point operations.
105
+ ///
106
+ /// Will return `None` if `Number` is negative or a NaN.
107
+ ///
108
+ /// ```
109
+ /// # use json::number::Number;
110
+ /// let price_a = Number::from(5.99);
111
+ /// let price_b = Number::from(7);
112
+ /// let price_c = Number::from(10.2);
113
+ ///
114
+ /// assert_eq!(price_a.as_fixed_point_u64(2), Some(599));
115
+ /// assert_eq!(price_b.as_fixed_point_u64(2), Some(700));
116
+ /// assert_eq!(price_c.as_fixed_point_u64(2), Some(1020));
117
+ /// ```
58
118
pub fn as_fixed_point_u64 ( & self , point : u16 ) -> Option < u64 > {
59
119
if self . category != POSITIVE {
60
120
return None ;
@@ -71,6 +131,17 @@ impl Number {
71
131
} )
72
132
}
73
133
134
+ /// Analog to `as_fixed_point_u64`, except returning a signed
135
+ /// `i64`, properly handling negative numbers.
136
+ ///
137
+ /// ```
138
+ /// # use json::number::Number;
139
+ /// let balance_a = Number::from(-1.49);
140
+ /// let balance_b = Number::from(42);
141
+ ///
142
+ /// assert_eq!(balance_a.as_fixed_point_i64(2), Some(-149));
143
+ /// assert_eq!(balance_b.as_fixed_point_i64(2), Some(4200));
144
+ /// ```
74
145
pub fn as_fixed_point_i64 ( & self , point : u16 ) -> Option < i64 > {
75
146
if self . is_nan ( ) {
76
147
return None ;
@@ -381,35 +452,38 @@ impl ops::Neg for Number {
381
452
}
382
453
}
383
454
384
- impl ops:: Mul for Number {
385
- type Output = Number ;
386
-
387
- #[ inline]
388
- fn mul ( self , other : Number ) -> Number {
389
- // If either is a NaN, return a NaN
390
- if ( self . category | other. category ) & NAN_MASK != 0 {
391
- NAN
392
- } else {
393
- Number {
394
- // If both signs are the same, xoring will produce 0.
395
- // If they are different, xoring will produce 1.
396
- // Xor again with 1 to get a proper proper sign!
397
- // Xor all the things! ^ _ ^
398
-
399
- category : self . category ^ other. category ^ POSITIVE ,
400
- exponent : self . exponent + other. exponent ,
401
- mantissa : self . mantissa * other. mantissa ,
402
- }
403
- }
404
- }
405
- }
406
-
407
- impl ops:: MulAssign for Number {
408
- #[ inline]
409
- fn mul_assign ( & mut self , other : Number ) {
410
- * self = * self * other;
411
- }
412
- }
455
+ // Commented out for now - not doing math ops for 0.10.0
456
+ // -----------------------------------------------------
457
+ //
458
+ // impl ops::Mul for Number {
459
+ // type Output = Number;
460
+
461
+ // #[inline]
462
+ // fn mul(self, other: Number) -> Number {
463
+ // // If either is a NaN, return a NaN
464
+ // if (self.category | other.category) & NAN_MASK != 0 {
465
+ // NAN
466
+ // } else {
467
+ // Number {
468
+ // // If both signs are the same, xoring will produce 0.
469
+ // // If they are different, xoring will produce 1.
470
+ // // Xor again with 1 to get a proper proper sign!
471
+ // // Xor all the things! ^ _ ^
472
+
473
+ // category: self.category ^ other.category ^ POSITIVE,
474
+ // exponent: self.exponent + other.exponent,
475
+ // mantissa: self.mantissa * other.mantissa,
476
+ // }
477
+ // }
478
+ // }
479
+ // }
480
+
481
+ // impl ops::MulAssign for Number {
482
+ // #[inline]
483
+ // fn mul_assign(&mut self, other: Number) {
484
+ // *self = *self * other;
485
+ // }
486
+ // }
413
487
414
488
#[ inline]
415
489
fn decimal_power ( e : u16 ) -> u64 {
0 commit comments