1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{chinese_vec, Chinese, ChineseFormat, Variant};
use digit_sequence::DigitSequence;

/// The integer part of a [Decimal].
///
/// **REQUIRED FEATURE**: `digit-sequence`.
pub type IntegerPart = i128;

/// Accurate real number.
///
/// It supports *unbounded* **fractional** precision and length,
/// but the **integer** part must be within the range of the
/// [IntegerPart] type alias; negative numbers are supported.
///
/// ```
/// use chinese_format::*;
/// use digit_sequence::*;
///
/// let decimal = Decimal {
///     integer: 96,
///     fractional: 753u16.into()
/// };
/// assert_eq!(decimal.to_chinese(Variant::Simplified), Chinese {
///     logograms: "九十六点七五三".to_string(),
///     omissible: false
/// });
/// assert_eq!(decimal.to_chinese(Variant::Traditional), Chinese {
///     logograms: "九十六點七五三".to_string(),
///     omissible: false
/// });
/// ```
///
/// **REQUIRED FEATURE**: `digit-sequence`.
pub struct Decimal {
    /// The digits *before* the decimal separator.
    pub integer: IntegerPart,

    /// The digits *after* the decimal separator.
    pub fractional: DigitSequence,
}

const COMMA: (&str, &str) = ("点", "點");

/// [Decimal] can be translated to [Chinese].
///
/// ```
/// use chinese_format::*;
/// use digit_sequence::*;
///
/// let integer_only = Decimal {
///     integer: 90,
///     fractional: DigitSequence::new()
/// };
/// assert_eq!(integer_only.to_chinese(Variant::Simplified), Chinese {
///     logograms: "九十".to_string(),
///     omissible: false
/// });
/// assert_eq!(integer_only.to_chinese(Variant::Traditional), Chinese {
///     logograms: "九十".to_string(),
///     omissible: false
/// });
///
/// let zero = Decimal {
///     integer: 0,
///     fractional: DigitSequence::new()
/// };
/// assert_eq!(zero.to_chinese(Variant::Simplified), Chinese {
///     logograms: "零".to_string(),
///     omissible: true
/// });
/// assert_eq!(zero.to_chinese(Variant::Traditional), Chinese {
///     logograms: "零".to_string(),
///     omissible: true
/// });
///
/// let integer_and_decimal = Decimal {
///     integer: 35,
///     fractional: 28039u16.into()
/// };
/// assert_eq!(integer_and_decimal.to_chinese(Variant::Simplified), Chinese {
///     logograms: "三十五点二八零三九".to_string(),
///     omissible: false
/// });
/// assert_eq!(integer_and_decimal.to_chinese(Variant::Traditional), Chinese {
///     logograms: "三十五點二八零三九".to_string(),
///     omissible: false
/// });
///
/// let zero_comma = Decimal {
///     integer: 0,
///     fractional: 9052u16.into()
/// };
/// assert_eq!(zero_comma.to_chinese(Variant::Simplified), Chinese {
///     logograms: "零点九零五二".to_string(),
///     omissible: false
/// });
/// assert_eq!(zero_comma.to_chinese(Variant::Traditional), Chinese {
///     logograms: "零點九零五二".to_string(),
///     omissible: false
/// });
///
/// let negative = Decimal {
///     integer: -487,
///     fractional: 309u16.into()
/// };
/// assert_eq!(negative.to_chinese(Variant::Simplified), Chinese {
///     logograms: "负四百八十七点三零九".to_string(),
///     omissible: false
/// });
/// assert_eq!(negative.to_chinese(Variant::Traditional), Chinese {
///     logograms: "負四百八十七點三零九".to_string(),
///     omissible: false
/// });
/// ```
impl ChineseFormat for Decimal {
    fn to_chinese(&self, variant: Variant) -> Chinese {
        if self.fractional.is_empty() {
            self.integer.to_chinese(variant)
        } else {
            chinese_vec!(variant, [self.integer, COMMA, self.fractional]).collect()
        }
    }
}