@@ -3,6 +3,7 @@ use std::num::FpCategory;
33use util:: grisu2;
44use util:: write:: write;
55
6+ /// NaN value represented in `Number` type. NaN is equal to itself.
67pub const NAN : Number = Number {
78 category : NAN_MASK ,
89 mantissa : 0 ,
@@ -13,14 +14,45 @@ const NEGATIVE: u8 = 0;
1314const POSITIVE : u8 = 1 ;
1415const NAN_MASK : u8 = !1 ;
1516
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.
1632#[ derive( Copy , Clone , Debug ) ]
1733pub 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
1838 category : u8 ,
39+
40+ // Decimal exponent, analog to `e` notation in string form.
1941 exponent : i16 ,
42+
43+ // Integer base before sing and exponent applied.
2044 mantissa : u64 ,
2145}
2246
2347impl 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+ /// ```
2456 #[ inline]
2557 pub fn from_parts ( positive : bool , mantissa : u64 , exponent : i16 ) -> Self {
2658 Number {
@@ -30,6 +62,17 @@ impl Number {
3062 }
3163 }
3264
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+ /// ```
3376 #[ inline]
3477 pub fn as_parts ( & self ) -> ( bool , u64 , i16 ) {
3578 ( self . category == POSITIVE , self . mantissa , self . exponent )
@@ -50,11 +93,28 @@ impl Number {
5093 self . category & NAN_MASK != 0
5194 }
5295
96+ /// Test if the number is NaN or has a zero value.
5397 #[ inline]
5498 pub fn is_empty ( & self ) -> bool {
5599 self . mantissa == 0 || self . is_nan ( )
56100 }
57101
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+ /// ```
58118 pub fn as_fixed_point_u64 ( & self , point : u16 ) -> Option < u64 > {
59119 if self . category != POSITIVE {
60120 return None ;
@@ -71,6 +131,17 @@ impl Number {
71131 } )
72132 }
73133
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+ /// ```
74145 pub fn as_fixed_point_i64 ( & self , point : u16 ) -> Option < i64 > {
75146 if self . is_nan ( ) {
76147 return None ;
@@ -381,35 +452,38 @@ impl ops::Neg for Number {
381452 }
382453}
383454
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+ // }
413487
414488#[ inline]
415489fn decimal_power ( e : u16 ) -> u64 {
0 commit comments