chinese_format/
decimal.rs

1use crate::{chinese_vec, Chinese, ChineseFormat, Variant};
2use digit_sequence::DigitSequence;
3
4/// The integer part of a [Decimal].
5///
6/// **REQUIRED FEATURE**: `digit-sequence`.
7pub type IntegerPart = i128;
8
9/// Accurate real number.
10///
11/// It supports *unbounded* **fractional** precision and length,
12/// but the **integer** part must be within the range of the
13/// [IntegerPart] type alias; negative numbers are supported.
14///
15/// ```
16/// use chinese_format::*;
17/// use digit_sequence::*;
18///
19/// let decimal = Decimal {
20///     integer: 96,
21///     fractional: 753u16.into()
22/// };
23/// assert_eq!(decimal.to_chinese(Variant::Simplified), Chinese {
24///     logograms: "九十六点七五三".to_string(),
25///     omissible: false
26/// });
27/// assert_eq!(decimal.to_chinese(Variant::Traditional), Chinese {
28///     logograms: "九十六點七五三".to_string(),
29///     omissible: false
30/// });
31/// ```
32///
33/// It is worth noting that [Decimal] supports both equality and ordering:
34///
35/// ```
36/// use chinese_format::*;
37/// use digit_sequence::DigitSequence;
38///
39/// let ninety = Decimal {
40///     integer: 90,
41///     fractional: DigitSequence::new()
42/// };
43///
44///
45/// let ninety_dot_five = Decimal {
46///     integer: 90,
47///     fractional: 5u8.into()
48/// };
49///
50///
51/// let ninety_dot_five_seven = Decimal {
52///     integer: 90,
53///     fractional: 57u8.into()
54/// };
55///
56/// let ninety_two = Decimal {
57///     integer: 92,
58///     fractional: DigitSequence::new()
59/// };
60///
61/// assert_eq!(ninety, ninety);
62/// assert_ne!(ninety, ninety_dot_five);
63///
64/// assert!(ninety < ninety_dot_five);
65/// assert!(ninety_dot_five < ninety_dot_five_seven);
66/// assert!(ninety_dot_five_seven < ninety_two);
67/// ```
68///
69/// **REQUIRED FEATURE**: `digit-sequence`.
70#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
71pub struct Decimal {
72    /// The digits *before* the decimal separator.
73    pub integer: IntegerPart,
74
75    /// The digits *after* the decimal separator.
76    pub fractional: DigitSequence,
77}
78
79const COMMA: (&str, &str) = ("点", "點");
80
81/// [Decimal] can be translated to [Chinese].
82///
83/// ```
84/// use chinese_format::*;
85/// use digit_sequence::*;
86///
87/// let integer_only = Decimal {
88///     integer: 90,
89///     fractional: DigitSequence::new()
90/// };
91/// assert_eq!(integer_only.to_chinese(Variant::Simplified), Chinese {
92///     logograms: "九十".to_string(),
93///     omissible: false
94/// });
95/// assert_eq!(integer_only.to_chinese(Variant::Traditional), Chinese {
96///     logograms: "九十".to_string(),
97///     omissible: false
98/// });
99///
100/// let zero = Decimal {
101///     integer: 0,
102///     fractional: DigitSequence::new()
103/// };
104/// assert_eq!(zero.to_chinese(Variant::Simplified), Chinese {
105///     logograms: "零".to_string(),
106///     omissible: true
107/// });
108/// assert_eq!(zero.to_chinese(Variant::Traditional), Chinese {
109///     logograms: "零".to_string(),
110///     omissible: true
111/// });
112///
113/// let integer_and_decimal = Decimal {
114///     integer: 35,
115///     fractional: 28039u16.into()
116/// };
117/// assert_eq!(integer_and_decimal.to_chinese(Variant::Simplified), Chinese {
118///     logograms: "三十五点二八零三九".to_string(),
119///     omissible: false
120/// });
121/// assert_eq!(integer_and_decimal.to_chinese(Variant::Traditional), Chinese {
122///     logograms: "三十五點二八零三九".to_string(),
123///     omissible: false
124/// });
125///
126/// let zero_comma = Decimal {
127///     integer: 0,
128///     fractional: 9052u16.into()
129/// };
130/// assert_eq!(zero_comma.to_chinese(Variant::Simplified), Chinese {
131///     logograms: "零点九零五二".to_string(),
132///     omissible: false
133/// });
134/// assert_eq!(zero_comma.to_chinese(Variant::Traditional), Chinese {
135///     logograms: "零點九零五二".to_string(),
136///     omissible: false
137/// });
138///
139/// let negative = Decimal {
140///     integer: -487,
141///     fractional: 309u16.into()
142/// };
143/// assert_eq!(negative.to_chinese(Variant::Simplified), Chinese {
144///     logograms: "负四百八十七点三零九".to_string(),
145///     omissible: false
146/// });
147/// assert_eq!(negative.to_chinese(Variant::Traditional), Chinese {
148///     logograms: "負四百八十七點三零九".to_string(),
149///     omissible: false
150/// });
151/// ```
152impl ChineseFormat for Decimal {
153    fn to_chinese(&self, variant: Variant) -> Chinese {
154        if self.fractional.is_empty() {
155            self.integer.to_chinese(variant)
156        } else {
157            chinese_vec!(variant, [self.integer, COMMA, self.fractional]).collect()
158        }
159    }
160}