1use schemars::JsonSchema;
2use serde::{de, ser, Deserialize, Deserializer, Serialize};
3use std::fmt::{self, Write};
4use std::ops;
5use std::str::FromStr;
6
7use crate::errors::StdError;
8
9use super::Fraction;
10use super::Isqrt;
11use super::Uint128;
12
13#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
17pub struct Decimal(#[schemars(with = "String")] Uint128);
18
19impl Decimal {
20 const DECIMAL_FRACTIONAL: Uint128 = Uint128::new(1_000_000_000_000_000_000u128); const DECIMAL_FRACTIONAL_SQUARED: Uint128 =
22 Uint128::new(1_000_000_000_000_000_000_000_000_000_000_000_000u128); const DECIMAL_PLACES: usize = 18; pub const MAX: Self = Self(Uint128::MAX);
26
27 pub const fn one() -> Self {
29 Decimal(Self::DECIMAL_FRACTIONAL)
30 }
31
32 pub const fn zero() -> Self {
34 Decimal(Uint128::zero())
35 }
36
37 pub fn percent(x: u64) -> Self {
39 Decimal(((x as u128) * 10_000_000_000_000_000).into())
40 }
41
42 pub fn permille(x: u64) -> Self {
44 Decimal(((x as u128) * 1_000_000_000_000_000).into())
45 }
46
47 pub fn from_ratio(numerator: impl Into<Uint128>, denominator: impl Into<Uint128>) -> Self {
49 let numerator: Uint128 = numerator.into();
50 let denominator: Uint128 = denominator.into();
51 if denominator.is_zero() {
52 panic!("Denominator must not be zero");
53 }
54
55 Decimal(
56 numerator.multiply_ratio(Self::DECIMAL_FRACTIONAL, denominator),
58 )
59 }
60
61 pub fn is_zero(&self) -> bool {
62 self.0.is_zero()
63 }
64
65 pub fn sqrt(&self) -> Self {
69 (0..=Self::DECIMAL_PLACES / 2)
77 .rev()
78 .find_map(|i| self.sqrt_with_precision(i))
79 .unwrap()
81 }
82
83 fn sqrt_with_precision(&self, precision: usize) -> Option<Self> {
88 let precision = precision as u32;
89
90 let inner_mul = 100u128.pow(precision);
91 self.0.checked_mul(inner_mul.into()).ok().map(|inner| {
92 let outer_mul = 10u128.pow(Self::DECIMAL_PLACES as u32 / 2 - precision);
93 Decimal(inner.isqrt().checked_mul(Uint128::from(outer_mul)).unwrap())
94 })
95 }
96}
97
98impl Fraction<u128> for Decimal {
99 #[inline]
100 fn numerator(&self) -> u128 {
101 self.0.u128()
102 }
103
104 #[inline]
105 fn denominator(&self) -> u128 {
106 Self::DECIMAL_FRACTIONAL.u128()
107 }
108
109 fn inv(&self) -> Option<Self> {
113 if self.is_zero() {
114 None
115 } else {
116 Some(Decimal(Self::DECIMAL_FRACTIONAL_SQUARED / self.0))
120 }
121 }
122}
123
124impl FromStr for Decimal {
125 type Err = StdError;
126
127 fn from_str(input: &str) -> Result<Self, Self::Err> {
134 let mut parts_iter = input.split('.');
135
136 let whole_part = parts_iter.next().unwrap(); let whole = whole_part
138 .parse::<Uint128>()
139 .map_err(|_| StdError::generic_err("Error parsing whole"))?;
140 let mut atomics = whole
141 .checked_mul(Self::DECIMAL_FRACTIONAL)
142 .map_err(|_| StdError::generic_err("Value too big"))?;
143
144 if let Some(fractional_part) = parts_iter.next() {
145 let fractional = fractional_part
146 .parse::<Uint128>()
147 .map_err(|_| StdError::generic_err("Error parsing fractional"))?;
148 let exp =
149 (Self::DECIMAL_PLACES.checked_sub(fractional_part.len())).ok_or_else(|| {
150 StdError::generic_err(format!(
151 "Cannot parse more than {} fractional digits",
152 Self::DECIMAL_PLACES
153 ))
154 })?;
155 debug_assert!(exp <= Self::DECIMAL_PLACES);
156 let fractional_factor = Uint128::from(10u128.pow(exp as u32));
157 atomics = atomics
158 .checked_add(
159 fractional.checked_mul(fractional_factor).unwrap(),
162 )
163 .map_err(|_| StdError::generic_err("Value too big"))?;
164 }
165
166 if parts_iter.next().is_some() {
167 return Err(StdError::generic_err("Unexpected number of dots"));
168 }
169
170 Ok(Decimal(atomics))
171 }
172}
173
174impl fmt::Display for Decimal {
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 let whole = (self.0) / Self::DECIMAL_FRACTIONAL;
177 let fractional = (self.0).checked_rem(Self::DECIMAL_FRACTIONAL).unwrap();
178
179 if fractional.is_zero() {
180 write!(f, "{}", whole)
181 } else {
182 let fractional_string =
183 format!("{:0>padding$}", fractional, padding = Self::DECIMAL_PLACES);
184 f.write_str(&whole.to_string())?;
185 f.write_char('.')?;
186 f.write_str(fractional_string.trim_end_matches('0'))?;
187 Ok(())
188 }
189 }
190}
191
192impl ops::Add for Decimal {
193 type Output = Self;
194
195 fn add(self, other: Self) -> Self {
196 Decimal(self.0 + other.0)
197 }
198}
199
200impl ops::Sub for Decimal {
201 type Output = Self;
202
203 fn sub(self, other: Self) -> Self {
204 Decimal(self.0 - other.0)
205 }
206}
207
208impl ops::Mul<Decimal> for Uint128 {
212 type Output = Self;
213
214 #[allow(clippy::suspicious_arithmetic_impl)]
215 fn mul(self, rhs: Decimal) -> Self::Output {
216 if self.is_zero() || rhs.is_zero() {
218 return Uint128::zero();
219 }
220 self.multiply_ratio(rhs.0, Decimal::DECIMAL_FRACTIONAL)
221 }
222}
223
224impl ops::Mul<Uint128> for Decimal {
225 type Output = Uint128;
226
227 fn mul(self, rhs: Uint128) -> Self::Output {
228 rhs * self
229 }
230}
231
232impl ops::Div<Uint128> for Decimal {
233 type Output = Self;
234
235 fn div(self, rhs: Uint128) -> Self::Output {
236 Decimal(self.0 / rhs)
237 }
238}
239
240impl ops::DivAssign<Uint128> for Decimal {
241 fn div_assign(&mut self, rhs: Uint128) {
242 self.0 /= rhs;
243 }
244}
245
246impl Serialize for Decimal {
248 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
249 where
250 S: ser::Serializer,
251 {
252 serializer.serialize_str(&self.to_string())
253 }
254}
255
256impl<'de> Deserialize<'de> for Decimal {
258 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
259 where
260 D: Deserializer<'de>,
261 {
262 deserializer.deserialize_str(DecimalVisitor)
263 }
264}
265
266struct DecimalVisitor;
267
268impl<'de> de::Visitor<'de> for DecimalVisitor {
269 type Value = Decimal;
270
271 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
272 formatter.write_str("string-encoded decimal")
273 }
274
275 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
276 where
277 E: de::Error,
278 {
279 match Decimal::from_str(v) {
280 Ok(d) => Ok(d),
281 Err(e) => Err(E::custom(format!("Error parsing decimal '{}': {}", v, e))),
282 }
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289 use crate::errors::StdError;
290 use crate::{from_slice, to_vec};
291
292 #[test]
293 fn decimal_one() {
294 let value = Decimal::one();
295 assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL);
296 }
297
298 #[test]
299 fn decimal_zero() {
300 let value = Decimal::zero();
301 assert!(value.0.is_zero());
302 }
303
304 #[test]
305 fn decimal_percent() {
306 let value = Decimal::percent(50);
307 assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(2u8));
308 }
309
310 #[test]
311 fn decimal_permille() {
312 let value = Decimal::permille(125);
313 assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(8u8));
314 }
315
316 #[test]
317 fn decimal_from_ratio_works() {
318 assert_eq!(Decimal::from_ratio(1u128, 1u128), Decimal::one());
320 assert_eq!(Decimal::from_ratio(53u128, 53u128), Decimal::one());
321 assert_eq!(Decimal::from_ratio(125u128, 125u128), Decimal::one());
322
323 assert_eq!(Decimal::from_ratio(3u128, 2u128), Decimal::percent(150));
325 assert_eq!(Decimal::from_ratio(150u128, 100u128), Decimal::percent(150));
326 assert_eq!(Decimal::from_ratio(333u128, 222u128), Decimal::percent(150));
327
328 assert_eq!(Decimal::from_ratio(1u64, 8u64), Decimal::permille(125));
330 assert_eq!(Decimal::from_ratio(125u64, 1000u64), Decimal::permille(125));
331
332 assert_eq!(
334 Decimal::from_ratio(1u64, 3u64),
335 Decimal(Uint128::from(333_333_333_333_333_333u128))
336 );
337
338 assert_eq!(
340 Decimal::from_ratio(2u64, 3u64),
341 Decimal(Uint128::from(666_666_666_666_666_666u128))
342 );
343
344 assert_eq!(Decimal::from_ratio(0u128, u128::MAX), Decimal::zero());
346 assert_eq!(Decimal::from_ratio(u128::MAX, u128::MAX), Decimal::one());
347 assert_eq!(
349 Decimal::from_ratio(340282366920938463463u128, 1u128),
350 Decimal::from_str("340282366920938463463").unwrap()
351 );
352 }
353
354 #[test]
355 #[should_panic(expected = "Denominator must not be zero")]
356 fn decimal_from_ratio_panics_for_zero_denominator() {
357 Decimal::from_ratio(1u128, 0u128);
358 }
359
360 #[test]
361 fn decimal_implements_fraction() {
362 let fraction = Decimal::from_str("1234.567").unwrap();
363 assert_eq!(fraction.numerator(), 1_234_567_000_000_000_000_000u128);
364 assert_eq!(fraction.denominator(), 1_000_000_000_000_000_000u128);
365 }
366
367 #[test]
368 fn decimal_from_str_works() {
369 assert_eq!(Decimal::from_str("0").unwrap(), Decimal::percent(0));
371 assert_eq!(Decimal::from_str("1").unwrap(), Decimal::percent(100));
372 assert_eq!(Decimal::from_str("5").unwrap(), Decimal::percent(500));
373 assert_eq!(Decimal::from_str("42").unwrap(), Decimal::percent(4200));
374 assert_eq!(Decimal::from_str("000").unwrap(), Decimal::percent(0));
375 assert_eq!(Decimal::from_str("001").unwrap(), Decimal::percent(100));
376 assert_eq!(Decimal::from_str("005").unwrap(), Decimal::percent(500));
377 assert_eq!(Decimal::from_str("0042").unwrap(), Decimal::percent(4200));
378
379 assert_eq!(Decimal::from_str("1.0").unwrap(), Decimal::percent(100));
381 assert_eq!(Decimal::from_str("1.5").unwrap(), Decimal::percent(150));
382 assert_eq!(Decimal::from_str("0.5").unwrap(), Decimal::percent(50));
383 assert_eq!(Decimal::from_str("0.123").unwrap(), Decimal::permille(123));
384
385 assert_eq!(Decimal::from_str("40.00").unwrap(), Decimal::percent(4000));
386 assert_eq!(Decimal::from_str("04.00").unwrap(), Decimal::percent(400));
387 assert_eq!(Decimal::from_str("00.40").unwrap(), Decimal::percent(40));
388 assert_eq!(Decimal::from_str("00.04").unwrap(), Decimal::percent(4));
389
390 assert_eq!(
392 Decimal::from_str("7.123456789012345678").unwrap(),
393 Decimal(Uint128::from(7123456789012345678u128))
394 );
395 assert_eq!(
396 Decimal::from_str("7.999999999999999999").unwrap(),
397 Decimal(Uint128::from(7999999999999999999u128))
398 );
399
400 assert_eq!(
402 Decimal::from_str("340282366920938463463.374607431768211455").unwrap(),
403 Decimal::MAX
404 );
405 }
406
407 #[test]
408 fn decimal_from_str_errors_for_broken_whole_part() {
409 match Decimal::from_str("").unwrap_err() {
410 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
411 e => panic!("Unexpected error: {:?}", e),
412 }
413
414 match Decimal::from_str(" ").unwrap_err() {
415 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
416 e => panic!("Unexpected error: {:?}", e),
417 }
418
419 match Decimal::from_str("-1").unwrap_err() {
420 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
421 e => panic!("Unexpected error: {:?}", e),
422 }
423 }
424
425 #[test]
426 fn decimal_from_str_errors_for_broken_fractinal_part() {
427 match Decimal::from_str("1.").unwrap_err() {
428 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
429 e => panic!("Unexpected error: {:?}", e),
430 }
431
432 match Decimal::from_str("1. ").unwrap_err() {
433 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
434 e => panic!("Unexpected error: {:?}", e),
435 }
436
437 match Decimal::from_str("1.e").unwrap_err() {
438 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
439 e => panic!("Unexpected error: {:?}", e),
440 }
441
442 match Decimal::from_str("1.2e3").unwrap_err() {
443 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
444 e => panic!("Unexpected error: {:?}", e),
445 }
446 }
447
448 #[test]
449 fn decimal_from_str_errors_for_more_than_18_fractional_digits() {
450 match Decimal::from_str("7.1234567890123456789").unwrap_err() {
451 StdError::GenericErr { msg, .. } => {
452 assert_eq!(msg, "Cannot parse more than 18 fractional digits",)
453 }
454 e => panic!("Unexpected error: {:?}", e),
455 }
456
457 match Decimal::from_str("7.1230000000000000000").unwrap_err() {
459 StdError::GenericErr { msg, .. } => {
460 assert_eq!(msg, "Cannot parse more than 18 fractional digits")
461 }
462 e => panic!("Unexpected error: {:?}", e),
463 }
464 }
465
466 #[test]
467 fn decimal_from_str_errors_for_invalid_number_of_dots() {
468 match Decimal::from_str("1.2.3").unwrap_err() {
469 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Unexpected number of dots"),
470 e => panic!("Unexpected error: {:?}", e),
471 }
472
473 match Decimal::from_str("1.2.3.4").unwrap_err() {
474 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Unexpected number of dots"),
475 e => panic!("Unexpected error: {:?}", e),
476 }
477 }
478
479 #[test]
480 fn decimal_from_str_errors_for_more_than_max_value() {
481 match Decimal::from_str("340282366920938463464").unwrap_err() {
483 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
484 e => panic!("Unexpected error: {:?}", e),
485 }
486
487 match Decimal::from_str("340282366920938463464.0").unwrap_err() {
489 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
490 e => panic!("Unexpected error: {:?}", e),
491 }
492 match Decimal::from_str("340282366920938463463.374607431768211456").unwrap_err() {
493 StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
494 e => panic!("Unexpected error: {:?}", e),
495 }
496 }
497
498 #[test]
499 fn decimal_is_zero_works() {
500 assert!(Decimal::zero().is_zero());
501 assert!(Decimal::percent(0).is_zero());
502 assert!(Decimal::permille(0).is_zero());
503
504 assert!(!Decimal::one().is_zero());
505 assert!(!Decimal::percent(123).is_zero());
506 assert!(!Decimal::permille(1234).is_zero());
507 }
508
509 #[test]
510 fn decimal_inv_works() {
511 assert_eq!(Decimal::zero().inv(), None);
513
514 assert_eq!(Decimal::one().inv(), Some(Decimal::one()));
516
517 assert_eq!(
519 Decimal::from_str("2").unwrap().inv(),
520 Some(Decimal::from_str("0.5").unwrap())
521 );
522 assert_eq!(
523 Decimal::from_str("20").unwrap().inv(),
524 Some(Decimal::from_str("0.05").unwrap())
525 );
526 assert_eq!(
527 Decimal::from_str("200").unwrap().inv(),
528 Some(Decimal::from_str("0.005").unwrap())
529 );
530 assert_eq!(
531 Decimal::from_str("2000").unwrap().inv(),
532 Some(Decimal::from_str("0.0005").unwrap())
533 );
534
535 assert_eq!(
537 Decimal::from_str("3").unwrap().inv(),
538 Some(Decimal::from_str("0.333333333333333333").unwrap())
539 );
540 assert_eq!(
541 Decimal::from_str("6").unwrap().inv(),
542 Some(Decimal::from_str("0.166666666666666666").unwrap())
543 );
544
545 assert_eq!(
547 Decimal::from_str("0.5").unwrap().inv(),
548 Some(Decimal::from_str("2").unwrap())
549 );
550 assert_eq!(
551 Decimal::from_str("0.05").unwrap().inv(),
552 Some(Decimal::from_str("20").unwrap())
553 );
554 assert_eq!(
555 Decimal::from_str("0.005").unwrap().inv(),
556 Some(Decimal::from_str("200").unwrap())
557 );
558 assert_eq!(
559 Decimal::from_str("0.0005").unwrap().inv(),
560 Some(Decimal::from_str("2000").unwrap())
561 );
562 }
563
564 #[test]
565 fn decimal_add() {
566 let value = Decimal::one() + Decimal::percent(50); assert_eq!(
568 value.0,
569 Decimal::DECIMAL_FRACTIONAL * Uint128::from(3u8) / Uint128::from(2u8)
570 );
571 }
572
573 #[test]
574 #[should_panic(expected = "attempt to add with overflow")]
575 fn decimal_add_overflow_panics() {
576 let _value = Decimal::MAX + Decimal::percent(50);
577 }
578
579 #[test]
580 fn decimal_sub() {
581 let value = Decimal::one() - Decimal::percent(50); assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(2u8));
583 }
584
585 #[test]
586 #[should_panic(expected = "attempt to subtract with overflow")]
587 fn decimal_sub_overflow_panics() {
588 let _value = Decimal::zero() - Decimal::percent(50);
589 }
590
591 #[test]
592 fn uint128_decimal_multiply() {
594 let left = Uint128::new(300);
596 let right = Decimal::one() + Decimal::percent(50); assert_eq!(left * right, Uint128::new(450));
598
599 let left = Uint128::new(300);
601 let right = Decimal::zero();
602 assert_eq!(left * right, Uint128::new(0));
603
604 let left = Uint128::new(0);
606 let right = Decimal::one() + Decimal::percent(50); assert_eq!(left * right, Uint128::new(0));
608 }
609
610 #[test]
611 fn decimal_uint128_multiply() {
613 let left = Decimal::one() + Decimal::percent(50); let right = Uint128::new(300);
616 assert_eq!(left * right, Uint128::new(450));
617
618 let left = Decimal::zero();
620 let right = Uint128::new(300);
621 assert_eq!(left * right, Uint128::new(0));
622
623 let left = Decimal::one() + Decimal::percent(50); let right = Uint128::new(0);
626 assert_eq!(left * right, Uint128::new(0));
627 }
628
629 #[test]
630 fn decimal_uint128_division() {
631 let left = Decimal::percent(150); let right = Uint128::new(3);
634 assert_eq!(left / right, Decimal::percent(50));
635
636 let left = Decimal::zero();
638 let right = Uint128::new(300);
639 assert_eq!(left / right, Decimal::zero());
640 }
641
642 #[test]
643 #[should_panic(expected = "attempt to divide by zero")]
644 fn decimal_uint128_divide_by_zero() {
645 let left = Decimal::percent(150); let right = Uint128::new(0);
647 let _result = left / right;
648 }
649
650 #[test]
651 fn decimal_uint128_div_assign() {
652 let mut dec = Decimal::percent(150); dec /= Uint128::new(3);
655 assert_eq!(dec, Decimal::percent(50));
656
657 let mut dec = Decimal::zero();
659 dec /= Uint128::new(300);
660 assert_eq!(dec, Decimal::zero());
661 }
662
663 #[test]
664 #[should_panic(expected = "attempt to divide by zero")]
665 fn decimal_uint128_div_assign_by_zero() {
666 let mut dec = Decimal::percent(50);
668 dec /= Uint128::new(0);
669 }
670
671 #[test]
672 fn decimal_uint128_sqrt() {
673 assert_eq!(Decimal::percent(900).sqrt(), Decimal::percent(300));
674
675 assert!(Decimal::percent(316) < Decimal::percent(1000).sqrt());
676 assert!(Decimal::percent(1000).sqrt() < Decimal::percent(317));
677 }
678
679 #[test]
681 fn decimal_uint128_sqrt_is_precise() {
682 assert_eq!(
683 Decimal::from_str("2").unwrap().sqrt(),
684 Decimal::from_str("1.414213562373095048").unwrap() );
686 }
687
688 #[test]
689 fn decimal_uint128_sqrt_does_not_overflow() {
690 assert_eq!(
691 Decimal::from_str("400").unwrap().sqrt(),
692 Decimal::from_str("20").unwrap()
693 );
694 }
695
696 #[test]
697 fn decimal_uint128_sqrt_intermediate_precision_used() {
698 assert_eq!(
699 Decimal::from_str("400001").unwrap().sqrt(),
700 Decimal::from_str("632.456322602596803200").unwrap()
704 );
705 }
706
707 #[test]
708 fn decimal_to_string() {
709 assert_eq!(Decimal::zero().to_string(), "0");
711 assert_eq!(Decimal::one().to_string(), "1");
712 assert_eq!(Decimal::percent(500).to_string(), "5");
713
714 assert_eq!(Decimal::percent(125).to_string(), "1.25");
716 assert_eq!(Decimal::percent(42638).to_string(), "426.38");
717 assert_eq!(Decimal::percent(3).to_string(), "0.03");
718 assert_eq!(Decimal::permille(987).to_string(), "0.987");
719
720 assert_eq!(
721 Decimal(Uint128::from(1u128)).to_string(),
722 "0.000000000000000001"
723 );
724 assert_eq!(
725 Decimal(Uint128::from(10u128)).to_string(),
726 "0.00000000000000001"
727 );
728 assert_eq!(
729 Decimal(Uint128::from(100u128)).to_string(),
730 "0.0000000000000001"
731 );
732 assert_eq!(
733 Decimal(Uint128::from(1000u128)).to_string(),
734 "0.000000000000001"
735 );
736 assert_eq!(
737 Decimal(Uint128::from(10000u128)).to_string(),
738 "0.00000000000001"
739 );
740 assert_eq!(
741 Decimal(Uint128::from(100000u128)).to_string(),
742 "0.0000000000001"
743 );
744 assert_eq!(
745 Decimal(Uint128::from(1000000u128)).to_string(),
746 "0.000000000001"
747 );
748 assert_eq!(
749 Decimal(Uint128::from(10000000u128)).to_string(),
750 "0.00000000001"
751 );
752 assert_eq!(
753 Decimal(Uint128::from(100000000u128)).to_string(),
754 "0.0000000001"
755 );
756 assert_eq!(
757 Decimal(Uint128::from(1000000000u128)).to_string(),
758 "0.000000001"
759 );
760 assert_eq!(
761 Decimal(Uint128::from(10000000000u128)).to_string(),
762 "0.00000001"
763 );
764 assert_eq!(
765 Decimal(Uint128::from(100000000000u128)).to_string(),
766 "0.0000001"
767 );
768 assert_eq!(
769 Decimal(Uint128::from(10000000000000u128)).to_string(),
770 "0.00001"
771 );
772 assert_eq!(
773 Decimal(Uint128::from(100000000000000u128)).to_string(),
774 "0.0001"
775 );
776 assert_eq!(
777 Decimal(Uint128::from(1000000000000000u128)).to_string(),
778 "0.001"
779 );
780 assert_eq!(
781 Decimal(Uint128::from(10000000000000000u128)).to_string(),
782 "0.01"
783 );
784 assert_eq!(
785 Decimal(Uint128::from(100000000000000000u128)).to_string(),
786 "0.1"
787 );
788 }
789
790 #[test]
791 fn decimal_serialize() {
792 assert_eq!(to_vec(&Decimal::zero()).unwrap(), br#""0""#);
793 assert_eq!(to_vec(&Decimal::one()).unwrap(), br#""1""#);
794 assert_eq!(to_vec(&Decimal::percent(8)).unwrap(), br#""0.08""#);
795 assert_eq!(to_vec(&Decimal::percent(87)).unwrap(), br#""0.87""#);
796 assert_eq!(to_vec(&Decimal::percent(876)).unwrap(), br#""8.76""#);
797 assert_eq!(to_vec(&Decimal::percent(8765)).unwrap(), br#""87.65""#);
798 }
799
800 #[test]
801 fn decimal_deserialize() {
802 assert_eq!(from_slice::<Decimal>(br#""0""#).unwrap(), Decimal::zero());
803 assert_eq!(from_slice::<Decimal>(br#""1""#).unwrap(), Decimal::one());
804 assert_eq!(from_slice::<Decimal>(br#""000""#).unwrap(), Decimal::zero());
805 assert_eq!(from_slice::<Decimal>(br#""001""#).unwrap(), Decimal::one());
806
807 assert_eq!(
808 from_slice::<Decimal>(br#""0.08""#).unwrap(),
809 Decimal::percent(8)
810 );
811 assert_eq!(
812 from_slice::<Decimal>(br#""0.87""#).unwrap(),
813 Decimal::percent(87)
814 );
815 assert_eq!(
816 from_slice::<Decimal>(br#""8.76""#).unwrap(),
817 Decimal::percent(876)
818 );
819 assert_eq!(
820 from_slice::<Decimal>(br#""87.65""#).unwrap(),
821 Decimal::percent(8765)
822 );
823 }
824}