Skip to content

Commit c2c6de5

Browse files
committed
Added as_fixed_point_u64 and as_fixed_point_i64 methods #79
1 parent e1cce3f commit c2c6de5

File tree

3 files changed

+131
-2
lines changed

3 files changed

+131
-2
lines changed

src/number.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl Number {
4242

4343
#[inline]
4444
pub fn is_zero(&self) -> bool {
45-
self.mantissa == 0
45+
self.mantissa == 0 && !self.is_nan()
4646
}
4747

4848
#[inline]
@@ -52,7 +52,47 @@ impl Number {
5252

5353
#[inline]
5454
pub fn is_empty(&self) -> bool {
55-
self.is_zero() || self.is_nan()
55+
self.mantissa == 0 || self.is_nan()
56+
}
57+
58+
pub fn as_fixed_point_u64(&self, point: u16) -> Option<u64> {
59+
if self.category != POSITIVE {
60+
return None;
61+
}
62+
63+
let e_diff = point as i16 + self.exponent;
64+
65+
Some(if e_diff == 0 {
66+
self.mantissa
67+
} else if e_diff < 0 {
68+
// TODO: use cached powers
69+
self.mantissa.wrapping_div(10u64.pow(-e_diff as u32))
70+
} else {
71+
// TODO: use cached powers
72+
self.mantissa.wrapping_mul(10u64.pow(e_diff as u32))
73+
})
74+
}
75+
76+
pub fn as_fixed_point_i64(&self, point: u16) -> Option<i64> {
77+
if self.is_nan() {
78+
return None;
79+
}
80+
81+
let num = if self.is_sign_positive() {
82+
self.mantissa as i64
83+
} else {
84+
-(self.mantissa as i64)
85+
};
86+
87+
let e_diff = point as i16 + self.exponent;
88+
89+
Some(if e_diff == 0 {
90+
num
91+
} else if e_diff < 0 {
92+
num.wrapping_div(10i64.pow(-e_diff as u32))
93+
} else {
94+
num.wrapping_mul(10i64.pow(e_diff as u32))
95+
})
5696
}
5797
}
5898

src/value.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,20 @@ impl JsonValue {
195195
}
196196
}
197197

198+
pub fn as_fixed_point_u64(&self, point: u16) -> Option<u64> {
199+
match *self {
200+
JsonValue::Number(ref value) => value.as_fixed_point_u64(point),
201+
_ => None
202+
}
203+
}
204+
205+
pub fn as_fixed_point_i64(&self, point: u16) -> Option<i64> {
206+
match *self {
207+
JsonValue::Number(ref value) => value.as_fixed_point_i64(point),
208+
_ => None
209+
}
210+
}
211+
198212
/// Take over the ownership of the value, leaving `Null` in it's place.
199213
///
200214
/// ## Example

tests/lib.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,29 @@ mod unit {
5858
assert_eq!(number.as_i32(), Some(40_000));
5959
}
6060

61+
#[test]
62+
fn as_fixed_point() {
63+
let number = JsonValue::from(3.14);
64+
65+
assert_eq!(number.as_fixed_point_u64(4).unwrap(), 31400_u64);
66+
assert_eq!(number.as_fixed_point_u64(2).unwrap(), 314_u64);
67+
assert_eq!(number.as_fixed_point_u64(0).unwrap(), 3_u64);
68+
69+
assert_eq!(number.as_fixed_point_i64(4).unwrap(), 31400_i64);
70+
assert_eq!(number.as_fixed_point_i64(2).unwrap(), 314_i64);
71+
assert_eq!(number.as_fixed_point_i64(0).unwrap(), 3_i64);
72+
73+
let number = JsonValue::from(-3.14);
74+
75+
assert_eq!(number.as_fixed_point_u64(4), None);
76+
assert_eq!(number.as_fixed_point_u64(2), None);
77+
assert_eq!(number.as_fixed_point_u64(0), None);
78+
79+
assert_eq!(number.as_fixed_point_i64(4).unwrap(), -31400_i64);
80+
assert_eq!(number.as_fixed_point_i64(2).unwrap(), -314_i64);
81+
assert_eq!(number.as_fixed_point_i64(0).unwrap(), -3_i64);
82+
}
83+
6184
#[test]
6285
fn is_as_boolean() {
6386
let boolean = JsonValue::Boolean(true);
@@ -1261,6 +1284,30 @@ mod json_checker_pass {
12611284

12621285
mod number {
12631286
use super::json::number::Number;
1287+
use std::f64;
1288+
1289+
#[test]
1290+
fn is_nan() {
1291+
assert!(Number::from(f64::NAN).is_nan());
1292+
}
1293+
1294+
#[test]
1295+
fn is_zero() {
1296+
assert!(Number::from(0).is_zero());
1297+
assert!(Number::from_parts(true, 0, 0).is_zero());
1298+
assert!(Number::from_parts(true, 0, 100).is_zero());
1299+
assert!(Number::from_parts(true, 0, -100).is_zero());
1300+
assert!(Number::from_parts(false, 0, 0).is_zero());
1301+
assert!(Number::from_parts(false, 0, 100).is_zero());
1302+
assert!(Number::from_parts(false, 0, -100).is_zero());
1303+
assert!(!Number::from(f64::NAN).is_zero());
1304+
}
1305+
1306+
#[test]
1307+
fn is_empty() {
1308+
assert!(Number::from(0).is_empty());
1309+
assert!(Number::from(f64::NAN).is_empty());
1310+
}
12641311

12651312
#[test]
12661313
fn eq() {
@@ -1328,4 +1375,32 @@ mod number {
13281375

13291376
assert_eq!(f64::from(number), 2.225073858507201e-308);
13301377
}
1378+
1379+
#[test]
1380+
fn as_fixed_point_u64() {
1381+
assert_eq!(Number::from(1.2345).as_fixed_point_u64(4).unwrap(), 12345);
1382+
assert_eq!(Number::from(1.2345).as_fixed_point_u64(2).unwrap(), 123);
1383+
assert_eq!(Number::from(1.2345).as_fixed_point_u64(0).unwrap(), 1);
1384+
1385+
assert_eq!(Number::from(5).as_fixed_point_u64(0).unwrap(), 5);
1386+
assert_eq!(Number::from(5).as_fixed_point_u64(2).unwrap(), 500);
1387+
assert_eq!(Number::from(5).as_fixed_point_u64(4).unwrap(), 50000);
1388+
1389+
assert_eq!(Number::from(-1).as_fixed_point_u64(0), None);
1390+
assert_eq!(Number::from(f64::NAN).as_fixed_point_u64(0), None);
1391+
}
1392+
1393+
#[test]
1394+
fn as_fixed_point_i64() {
1395+
assert_eq!(Number::from(-1.2345).as_fixed_point_i64(4).unwrap(), -12345);
1396+
assert_eq!(Number::from(-1.2345).as_fixed_point_i64(2).unwrap(), -123);
1397+
assert_eq!(Number::from(-1.2345).as_fixed_point_i64(0).unwrap(), -1);
1398+
1399+
assert_eq!(Number::from(-5).as_fixed_point_i64(0).unwrap(), -5);
1400+
assert_eq!(Number::from(-5).as_fixed_point_i64(2).unwrap(), -500);
1401+
assert_eq!(Number::from(-5).as_fixed_point_i64(4).unwrap(), -50000);
1402+
1403+
assert_eq!(Number::from(-1).as_fixed_point_i64(0), Some(-1));
1404+
assert_eq!(Number::from(f64::NAN).as_fixed_point_i64(0), None);
1405+
}
13311406
}

0 commit comments

Comments
 (0)