1use std::{fmt, ops};
25#[cfg(feature = "serde-decimal")] use std::error;
26#[cfg(feature = "serde-decimal")] use std::str::FromStr;
27
28#[cfg(feature = "serde-decimal")] use serde;
29#[cfg(feature = "serde-decimal")] use strason::{self, Json};
30
31#[derive(Copy, Clone, Debug, Eq, Ord)]
33pub struct Decimal {
34 mantissa: i64,
35 exponent: usize,
36}
37
38#[derive(Copy, Clone, Debug, Eq, Ord)]
40pub struct UDecimal {
41 mantissa: u64,
42 exponent: usize,
43}
44
45impl PartialEq<Decimal> for Decimal {
46 fn eq(&self, other: &Decimal) -> bool {
47 use std::cmp::max;
48 let exp = max(self.exponent(), other.exponent());
49 self.integer_value(exp) == other.integer_value(exp)
50 }
51}
52
53impl PartialOrd<Decimal> for Decimal {
54 fn partial_cmp(&self, other: &Decimal) -> Option<::std::cmp::Ordering> {
55 use std::cmp::max;
56 let exp = max(self.exponent(), other.exponent());
57 self.integer_value(exp).partial_cmp(&other.integer_value(exp))
58 }
59}
60
61impl fmt::Display for Decimal {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 let ten = 10i64.pow(self.exponent as u32);
64 let int_part = self.mantissa / ten;
65 let dec_part = (self.mantissa % ten).abs();
66 if int_part == 0 && self.mantissa < 0 {
67 write!(f, "-{}.{:02$}", int_part, dec_part, self.exponent)
68 } else {
69 write!(f, "{}.{:02$}", int_part, dec_part, self.exponent)
70 }
71 }
72}
73
74impl ops::Add for Decimal {
75 type Output = Decimal;
76
77 #[inline]
78 fn add(self, other: Decimal) -> Decimal {
79 if self.exponent > other.exponent {
80 Decimal {
81 mantissa: other.mantissa * 10i64.pow((self.exponent - other.exponent) as u32) + self.mantissa,
82 exponent: self.exponent
83 }
84 } else {
85 Decimal {
86 mantissa: self.mantissa * 10i64.pow((other.exponent - self.exponent) as u32) + other.mantissa,
87 exponent: other.exponent
88 }
89 }
90 }
91}
92
93impl ops::Neg for Decimal {
94 type Output = Decimal;
95 #[inline]
96 fn neg(self) -> Decimal { Decimal { mantissa: -self.mantissa, exponent: self.exponent } }
97}
98
99impl ops::Sub for Decimal {
100 type Output = Decimal;
101 #[inline]
102 fn sub(self, other: Decimal) -> Decimal { self + (-other) }
103}
104
105impl Decimal {
106 pub fn new(mantissa: i64, exponent: usize) -> Decimal {
108 Decimal {
109 mantissa: mantissa,
110 exponent: exponent
111 }
112 }
113
114 #[inline]
116 pub fn mantissa(&self) -> i64 { self.mantissa }
117 #[inline]
119 pub fn exponent(&self) -> usize { self.exponent }
120
121 pub fn integer_value(&self, exponent: usize) -> i64 {
125 if exponent < self.exponent {
126 self.mantissa / 10i64.pow((self.exponent - exponent) as u32)
127 } else {
128 self.mantissa * 10i64.pow((exponent - self.exponent) as u32)
129 }
130 }
131
132 #[inline]
134 pub fn nonnegative(&self) -> bool { self.mantissa >= 0 }
135
136 #[cfg(feature = "serde-decimal")]
138 fn parse_decimal(s: &str) -> Result<Decimal, ParseDecimalError> {
139 let mut negative = false;
142 let mut past_dec = false;
143 let mut exponent = 0;
144 let mut mantissa = 0i64;
145
146 for b in s.as_bytes() {
147 match *b {
148 b'-' => { negative = true; }
149 b'0'...b'9' => {
150 match 10i64.checked_mul(mantissa) {
151 None => return Err(ParseDecimalError::TooBig),
152 Some(n) => {
153 match n.checked_add((b - b'0') as i64) {
154 None => return Err(ParseDecimalError::TooBig),
155 Some(n) => mantissa = n,
156 }
157 }
158 }
159 if past_dec {
160 exponent += 1;
161 if exponent > 18 {
162 return Err(ParseDecimalError::TooBig);
163 }
164 }
165 }
166 b'.' => { past_dec = true; }
167 _ => { }
168 }
169 }
170 if negative { mantissa *= -1; }
171 Ok(Decimal {
172 mantissa: mantissa,
173 exponent: exponent,
174 })
175 }
176}
177
178#[cfg(feature = "serde-decimal")]
179impl FromStr for Decimal {
180 type Err = ParseDecimalError;
181
182 fn from_str(s: &str) -> Result<Self, Self::Err> {
184 Json::from_str(s)?
185 .num()
186 .ok_or(ParseDecimalError::NotANumber)
187 .and_then(Decimal::parse_decimal)
188 }
189}
190
191#[cfg(feature = "serde-decimal")]
192impl<'de> serde::Deserialize<'de> for Decimal {
193 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
200 where
201 D: serde::Deserializer<'de>,
202 {
203 use serde::de;
204
205 Json::deserialize(deserializer)?
206 .num()
207 .ok_or(de::Error::custom("expected decimal, got non-numeric"))
208 .and_then(|s| Decimal::parse_decimal(s).map_err(de::Error::custom))
209 }
210}
211
212#[cfg(feature = "serde-decimal")]
213impl serde::Serialize for Decimal {
214 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
222 where
223 S: serde::Serializer,
224 {
225 let json = Json::from_str(&self.to_string()).unwrap();
226 json.serialize(serializer)
227 }
228}
229
230impl PartialEq<UDecimal> for UDecimal {
231 fn eq(&self, other: &UDecimal) -> bool {
232 use std::cmp::max;
233 let exp = max(self.exponent(), other.exponent());
234 self.integer_value(exp) == other.integer_value(exp)
235 }
236}
237
238impl PartialOrd<UDecimal> for UDecimal {
239 fn partial_cmp(&self, other: &UDecimal) -> Option<::std::cmp::Ordering> {
240 use std::cmp::max;
241 let exp = max(self.exponent(), other.exponent());
242 self.integer_value(exp).partial_cmp(&other.integer_value(exp))
243 }
244}
245
246impl fmt::Display for UDecimal {
247 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
248 let ten = 10u64.pow(self.exponent as u32);
249 let int_part = self.mantissa / ten;
250 let dec_part = self.mantissa % ten;
251 write!(f, "{}.{:02$}", int_part, dec_part, self.exponent)
252 }
253}
254
255impl ops::Add for UDecimal {
256 type Output = UDecimal;
257
258 #[inline]
259 fn add(self, other: UDecimal) -> UDecimal {
260 if self.exponent > other.exponent {
261 UDecimal {
262 mantissa: other.mantissa * 10u64.pow((self.exponent - other.exponent) as u32) + self.mantissa,
263 exponent: self.exponent
264 }
265 } else {
266 UDecimal {
267 mantissa: self.mantissa * 10u64.pow((other.exponent - self.exponent) as u32) + other.mantissa,
268 exponent: other.exponent
269 }
270 }
271 }
272}
273
274impl UDecimal {
275 pub fn new(mantissa: u64, exponent: usize) -> UDecimal {
277 UDecimal {
278 mantissa: mantissa,
279 exponent: exponent
280 }
281 }
282
283 #[inline]
285 pub fn mantissa(&self) -> u64 { self.mantissa }
286 #[inline]
288 pub fn exponent(&self) -> usize { self.exponent }
289
290 pub fn integer_value(&self, exponent: usize) -> u64 {
294 if exponent < self.exponent {
295 self.mantissa / 10u64.pow((self.exponent - exponent) as u32)
296 } else {
297 self.mantissa * 10u64.pow((exponent - self.exponent) as u32)
298 }
299 }
300
301 #[cfg(feature = "serde-decimal")]
303 fn parse_udecimal(s: &str) -> Result<UDecimal, ParseDecimalError> {
304 let mut past_dec = false;
307 let mut exponent = 0;
308 let mut mantissa = 0u64;
309
310 for b in s.as_bytes() {
311 match *b {
312 b'0'...b'9' => {
313 match 10u64.checked_mul(mantissa) {
314 None => return Err(ParseDecimalError::TooBig),
315 Some(n) => {
316 match n.checked_add((b - b'0') as u64) {
317 None => return Err(ParseDecimalError::TooBig),
318 Some(n) => mantissa = n,
319 }
320 }
321 }
322 if past_dec {
323 exponent += 1;
324 if exponent > 18 {
325 return Err(ParseDecimalError::TooBig);
326 }
327 }
328 }
329 b'.' => { past_dec = true; }
330 _ => { }
331 }
332 }
333 Ok(UDecimal {
334 mantissa: mantissa,
335 exponent: exponent,
336 })
337 }
338}
339
340#[cfg(feature = "serde-decimal")]
341impl FromStr for UDecimal {
342 type Err = ParseDecimalError;
343
344 fn from_str(s: &str) -> Result<Self, Self::Err> {
346 Json::from_str(s)?
347 .num()
348 .ok_or(ParseDecimalError::NotANumber)
349 .and_then(UDecimal::parse_udecimal)
350 }
351}
352
353#[cfg(feature = "serde-decimal")]
354impl<'de> serde::Deserialize<'de> for UDecimal {
355 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
362 where
363 D: serde::Deserializer<'de>,
364 {
365 use serde::de;
366
367 Json::deserialize(deserializer)?
368 .num()
369 .ok_or(de::Error::custom("expected decimal, got non-numeric"))
370 .and_then(|s| UDecimal::parse_udecimal(s).map_err(de::Error::custom))
371 }
372}
373
374#[cfg(feature = "serde-decimal")]
375impl serde::Serialize for UDecimal {
376 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
384 where
385 S: serde::Serializer,
386 {
387 let json = Json::from_str(&self.to_string()).unwrap();
388 json.serialize(serializer)
389 }
390}
391
392#[cfg(feature = "serde-decimal")]
394#[derive(Debug)]
395pub enum ParseDecimalError {
396 Json(strason::Error),
398 NotANumber,
400 TooBig,
402}
403
404#[cfg(feature = "serde-decimal")]
405#[doc(hidden)]
406impl From<strason::Error> for ParseDecimalError {
407 fn from(e: strason::Error) -> ParseDecimalError {
408 ParseDecimalError::Json(e)
409 }
410}
411
412#[cfg(feature = "serde-decimal")]
413impl fmt::Display for ParseDecimalError {
414 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
415 match *self {
416 ParseDecimalError::Json(ref e) => fmt::Display::fmt(e, fmt),
417 ParseDecimalError::NotANumber => fmt.write_str("not a valid JSON number"),
418 ParseDecimalError::TooBig => fmt.write_str("number is too big"),
419 }
420 }
421}
422
423#[cfg(feature = "serde-decimal")]
424impl error::Error for ParseDecimalError {
425 fn description(&self) -> &str {
426 match *self {
427 ParseDecimalError::Json(ref e) => e.description(),
428 ParseDecimalError::NotANumber => "not a valid JSON number",
429 ParseDecimalError::TooBig => "number is too big",
430 }
431 }
432
433 fn cause(&self) -> Option<&error::Error> {
434 match *self {
435 ParseDecimalError::Json(ref e) => Some(e),
436 _ => None,
437 }
438 }
439}
440
441#[cfg(test)]
442mod tests {
443 use super::*;
444 #[cfg(feature = "serde-decimal")]
445 use strason::Json;
446
447 #[test]
448 fn integer_value() {
449 let d = Decimal::new(12345678, 4);
450 assert_eq!(d.mantissa(), 12345678);
451 assert_eq!(d.exponent(), 4);
452
453 assert_eq!(d.integer_value(0), 1234);
454 assert_eq!(d.integer_value(1), 12345);
455 assert_eq!(d.integer_value(2), 123456);
456 assert_eq!(d.integer_value(3), 1234567);
457 assert_eq!(d.integer_value(4), 12345678);
458 assert_eq!(d.integer_value(5), 123456780);
459 assert_eq!(d.integer_value(6), 1234567800);
460 assert_eq!(d.integer_value(7), 12345678000);
461 assert_eq!(d.integer_value(8), 123456780000);
462
463 let u = UDecimal::new(12345678, 4);
464 assert_eq!(u.mantissa(), 12345678);
465 assert_eq!(u.exponent(), 4);
466
467 assert_eq!(u.integer_value(0), 1234);
468 assert_eq!(u.integer_value(1), 12345);
469 assert_eq!(u.integer_value(2), 123456);
470 assert_eq!(u.integer_value(3), 1234567);
471 assert_eq!(u.integer_value(4), 12345678);
472 assert_eq!(u.integer_value(5), 123456780);
473 assert_eq!(u.integer_value(6), 1234567800);
474 assert_eq!(u.integer_value(7), 12345678000);
475 assert_eq!(u.integer_value(8), 123456780000);
476 }
477
478 #[cfg(feature = "serde-decimal")]
479 macro_rules! deserialize_round_trip(
480 ($dec:expr, $s:expr) => ({
481 let d = $dec;
482 let encoded = Json::from_serialize(&d).unwrap();
483 assert_eq!(encoded, Json::from_reader(&$s[..]).unwrap());
484 assert_eq!(encoded.to_bytes(), &$s[..]);
485
486 let mut decoded_res = encoded.into_deserialize();
488 if false { decoded_res = Ok($dec); }
489 let decoded = decoded_res.unwrap();
490 assert_eq!(decoded, d);
491 })
492 );
493
494 #[test]
495 #[cfg(feature = "serde-decimal")]
496 fn deserialize() {
497 deserialize_round_trip!(Decimal::new(0, 0), b"0.0");
498 deserialize_round_trip!(UDecimal::new(0, 0), b"0.0");
499
500 deserialize_round_trip!(Decimal::new(123456789001, 8), b"1234.56789001");
501 deserialize_round_trip!(UDecimal::new(123456789001, 8), b"1234.56789001");
502 deserialize_round_trip!(Decimal::new(-123456789001, 8), b"-1234.56789001");
503 deserialize_round_trip!(Decimal::new(123456789001, 1), b"12345678900.1");
504 deserialize_round_trip!(UDecimal::new(123456789001, 1), b"12345678900.1");
505 deserialize_round_trip!(Decimal::new(-123456789001, 1), b"-12345678900.1");
506 deserialize_round_trip!(Decimal::new(123456789001, 0), b"123456789001.0");
507 deserialize_round_trip!(UDecimal::new(123456789001, 0), b"123456789001.0");
508 deserialize_round_trip!(Decimal::new(-123456789001, 0), b"-123456789001.0");
509
510 deserialize_round_trip!(Decimal::new(123400000001, 8), b"1234.00000001");
511 deserialize_round_trip!(UDecimal::new(123400000001, 8), b"1234.00000001");
512 deserialize_round_trip!(Decimal::new(-123400000001, 8), b"-1234.00000001");
513 }
514
515 #[test]
516 fn equality() {
517 let d1 = Decimal::new(1234, 8);
518 let d2 = Decimal::new(12340, 9);
519 let d3 = Decimal::new(12340, 8);
520 assert_eq!(d1, d1);
521 assert_eq!(d1, d2);
522 assert!(d1 != d3);
523 assert!(d2 != d3);
524
525 assert!(d1 <= d1);
526 assert!(d2 <= d2);
527 assert!(d3 <= d3);
528 assert!(d1 <= d2);
529 assert!(d1 <= d3);
530 assert!(d3 > d1);
531 assert!(d3 > d2);
532 }
533
534 #[test]
535 fn arithmetic() {
536 let d1 = Decimal::new(5, 1); let d2 = Decimal::new(-2, 2); let d3 = Decimal::new(3, 0); let d4 = Decimal::new(0, 5); let u1 = UDecimal::new(5, 1); let u3 = UDecimal::new(3, 0); let u4 = UDecimal::new(0, 5); assert!(d1.nonnegative());
545 assert!(!d2.nonnegative());
546 assert!(d3.nonnegative());
547 assert!(d4.nonnegative());
548
549 assert_eq!(d1 + d2, Decimal::new(48, 2));
550 assert_eq!(d1 - d2, Decimal::new(52, 2));
551 assert_eq!(d1 + d3, Decimal::new(35, 1));
552 assert_eq!(u1 + u3, UDecimal::new(35, 1));
553 assert_eq!(d1 - d3, Decimal::new(-25, 1));
554 assert_eq!(d2 + d3, Decimal::new(298, 2));
555 assert_eq!(d2 - d3, Decimal::new(-302, 2));
556
557 assert_eq!(d1 + d4, d1);
558 assert_eq!(u1 + u4, u1);
559 assert_eq!(d1 - d4, d1);
560 assert_eq!(d1 + d4, d1 - d4);
561 assert_eq!(d4 + d4, d4);
562 assert_eq!(u4 + u4, u4);
563 }
564
565 #[test]
566 #[cfg(feature = "serde-decimal")]
567 fn json_parse() {
568 let json = Json::from_str("0.00980000").unwrap();
569 assert_eq!(json.to_bytes(), b"0.00980000");
570 let dec: Decimal = json.into_deserialize().unwrap();
571 assert_eq!(dec, Decimal::new(980000, 8));
572
573 let json = Json::from_str("0.00980000").unwrap();
574 assert_eq!(json.to_bytes(), b"0.00980000");
575 let dec: UDecimal = json.into_deserialize().unwrap();
576 assert_eq!(dec, UDecimal::new(980000, 8));
577
578 let json = Json::from_str("0.00980").unwrap();
579 assert_eq!(json.to_bytes(), b"0.00980");
580 let dec: Decimal = json.into_deserialize().unwrap();
581 assert_eq!(dec, Decimal::new(98000, 7));
582
583 let json = Json::from_str("0.00980").unwrap();
584 assert_eq!(json.to_bytes(), b"0.00980");
585 let dec: UDecimal = json.into_deserialize().unwrap();
586 assert_eq!(dec, UDecimal::new(98000, 7));
587 }
588
589 #[test]
590 #[cfg(feature = "serde-decimal")]
591 fn parse_decimal_udecimal() {
592 let dec = "0.00980000".parse::<Decimal>().unwrap();
593 assert_eq!(dec, Decimal::new(980000, 8));
594
595 let dec = "0.00980000".parse::<UDecimal>().unwrap();
596 assert_eq!(dec, UDecimal::new(980000, 8));
597
598 let dec = "0.00980".parse::<Decimal>().unwrap();
599 assert_eq!(dec, Decimal::new(98000, 7));
600
601 let dec = "0.00980".parse::<UDecimal>().unwrap();
602 assert_eq!(dec, UDecimal::new(98000, 7));
603 }
604}