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}