chinese_numerals/
shortscale.rs

1use crate::{characters::*, ChineseNumeralBase, Sign, Signed};
2
3/// Short scale integers (下数).
4///
5/// 「下数者,十十变之。若言十万曰亿,十亿曰兆,十兆曰京也。」
6#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
7pub struct ShortScaleInt {
8    pub(super) sign: Sign,
9    pub(super) data: u64,
10}
11
12impl ShortScaleInt {
13    pub(super) const MAX_ABS: u64 = 999_9999_9999_9999;
14
15    /// The maximum integer can be expressed in short scale.
16    pub const MAX: Self = Self {
17        sign: Sign::Pos,
18        data: Self::MAX_ABS,
19    };
20
21    /// The minimum integer can be expressed in short scale
22    pub const MIN: Self = Self {
23        sign: Sign::Neg,
24        data: Self::MAX_ABS,
25    };
26}
27
28impl ChineseNumeralBase for ShortScaleInt {
29    fn to_chars(&self) -> Vec<NumChar> {
30        let mut chars = Vec::new();
31        let mut num = *self.data();
32        let mut prev_rem = 1;
33
34        for exp in 9..=23 {
35            let rem = num % 10;
36            num /= 10;
37
38            if rem > 0 {
39                if !chars.is_empty() && prev_rem < 1 {
40                    chars.push(NUM_CHARS[0]);
41                }
42                if exp > 9 {
43                    chars.push(NUM_CHARS[exp]);
44                }
45                chars.push(NUM_CHARS[rem as usize]);
46            }
47            prev_rem = rem;
48        }
49        chars
50    }
51
52    fn to_chars_trimmed(&self) -> Vec<NumChar> {
53        let mut chars = self.to_chars();
54        if self.data() >= &10 && self.data() <= &19 {
55            let one = chars.pop();
56            debug_assert_eq!(one, Some(NumChar::One));
57        }
58        chars
59    }
60}