/rust/registry/src/index.crates.io-1949cf8c6b5b557f/icu_decimal-1.5.0/src/grouper.rs
Line | Count | Source |
1 | | // This file is part of ICU4X. For terms of use, please see the file |
2 | | // called LICENSE at the top level of the ICU4X source tree |
3 | | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | | |
5 | | //! Algorithms to determine where to position grouping separators. |
6 | | |
7 | | use crate::options::GroupingStrategy; |
8 | | use crate::provider::GroupingSizesV1; |
9 | | use core::cmp; |
10 | | |
11 | | /// Returns whether to display a grouping separator at the given magnitude. |
12 | | /// |
13 | | /// `upper_magnitude` is the magnitude of the highest-power digit, used for resolving minimum |
14 | | /// grouping digits. |
15 | 0 | pub fn check( |
16 | 0 | upper_magnitude: i16, |
17 | 0 | magnitude: i16, |
18 | 0 | strategy: GroupingStrategy, |
19 | 0 | sizes: &GroupingSizesV1, |
20 | 0 | ) -> bool { |
21 | 0 | let primary = if sizes.primary == 0 { |
22 | 0 | return false; |
23 | | } else { |
24 | 0 | sizes.primary as i16 |
25 | | }; |
26 | 0 | if magnitude < primary { |
27 | 0 | return false; |
28 | 0 | } |
29 | 0 | let min_grouping = { |
30 | | use GroupingStrategy::*; |
31 | 0 | match strategy { |
32 | 0 | Never => return false, |
33 | | // Note: Auto and Always are the same for FixedDecimalFormatter. |
34 | | // When currencies are implemented, this will change. |
35 | 0 | Auto | Always => cmp::max(1, sizes.min_grouping) as i16, |
36 | 0 | Min2 => cmp::max(2, sizes.min_grouping) as i16, |
37 | | } |
38 | | }; |
39 | 0 | if upper_magnitude < primary + min_grouping - 1 { |
40 | 0 | return false; |
41 | 0 | } |
42 | 0 | let secondary = if sizes.secondary == 0 { |
43 | 0 | primary |
44 | | } else { |
45 | 0 | sizes.secondary as i16 |
46 | | }; |
47 | 0 | let magnitude_prime = magnitude - primary; |
48 | 0 | if magnitude_prime % secondary == 0 { |
49 | 0 | return true; |
50 | 0 | } |
51 | 0 | false |
52 | 0 | } |
53 | | |
54 | | #[test] |
55 | | fn test_grouper() { |
56 | | use crate::options; |
57 | | use crate::provider::*; |
58 | | use crate::FixedDecimalFormatter; |
59 | | use fixed_decimal::FixedDecimal; |
60 | | use icu_locid::LanguageIdentifier; |
61 | | use icu_provider::prelude::*; |
62 | | use icu_provider_adapters::any_payload::AnyPayloadProvider; |
63 | | use writeable::assert_writeable_eq; |
64 | | |
65 | | let western_sizes = GroupingSizesV1 { |
66 | | min_grouping: 1, |
67 | | primary: 3, |
68 | | secondary: 3, |
69 | | }; |
70 | | let indic_sizes = GroupingSizesV1 { |
71 | | min_grouping: 1, |
72 | | primary: 3, |
73 | | secondary: 2, |
74 | | }; |
75 | | let western_sizes_min3 = GroupingSizesV1 { |
76 | | min_grouping: 3, |
77 | | primary: 3, |
78 | | secondary: 3, |
79 | | }; |
80 | | |
81 | | // primary=0 implies no grouping; the other fields are ignored |
82 | | let zero_test = GroupingSizesV1 { |
83 | | min_grouping: 0, |
84 | | primary: 0, |
85 | | secondary: 0, |
86 | | }; |
87 | | |
88 | | // secondary=0 implies that it inherits from primary |
89 | | let blank_secondary = GroupingSizesV1 { |
90 | | min_grouping: 0, |
91 | | primary: 3, |
92 | | secondary: 0, |
93 | | }; |
94 | | |
95 | | #[derive(Debug)] |
96 | | struct TestCase { |
97 | | strategy: GroupingStrategy, |
98 | | sizes: GroupingSizesV1, |
99 | | // Expected results for numbers with magnitude 3, 4, 5, and 6 |
100 | | expected: [&'static str; 4], |
101 | | } |
102 | | #[allow(clippy::redundant_clone)] |
103 | | let cases = [ |
104 | | TestCase { |
105 | | strategy: GroupingStrategy::Auto, |
106 | | sizes: western_sizes, |
107 | | expected: ["1,000", "10,000", "100,000", "1,000,000"], |
108 | | }, |
109 | | TestCase { |
110 | | strategy: GroupingStrategy::Min2, |
111 | | sizes: western_sizes, |
112 | | expected: ["1000", "10,000", "100,000", "1,000,000"], |
113 | | }, |
114 | | TestCase { |
115 | | strategy: GroupingStrategy::Auto, |
116 | | sizes: indic_sizes, |
117 | | expected: ["1,000", "10,000", "1,00,000", "10,00,000"], |
118 | | }, |
119 | | TestCase { |
120 | | strategy: GroupingStrategy::Min2, |
121 | | sizes: indic_sizes, |
122 | | expected: ["1000", "10,000", "1,00,000", "10,00,000"], |
123 | | }, |
124 | | TestCase { |
125 | | strategy: GroupingStrategy::Auto, |
126 | | sizes: western_sizes_min3, |
127 | | expected: ["1000", "10000", "100,000", "1,000,000"], |
128 | | }, |
129 | | TestCase { |
130 | | strategy: GroupingStrategy::Min2, |
131 | | sizes: western_sizes_min3, |
132 | | expected: ["1000", "10000", "100,000", "1,000,000"], |
133 | | }, |
134 | | TestCase { |
135 | | strategy: GroupingStrategy::Auto, |
136 | | sizes: zero_test, |
137 | | expected: ["1000", "10000", "100000", "1000000"], |
138 | | }, |
139 | | TestCase { |
140 | | strategy: GroupingStrategy::Min2, |
141 | | sizes: zero_test, |
142 | | expected: ["1000", "10000", "100000", "1000000"], |
143 | | }, |
144 | | TestCase { |
145 | | strategy: GroupingStrategy::Auto, |
146 | | sizes: blank_secondary, |
147 | | expected: ["1,000", "10,000", "100,000", "1,000,000"], |
148 | | }, |
149 | | TestCase { |
150 | | strategy: GroupingStrategy::Min2, |
151 | | sizes: blank_secondary, |
152 | | expected: ["1000", "10,000", "100,000", "1,000,000"], |
153 | | }, |
154 | | ]; |
155 | | for cas in &cases { |
156 | | for i in 0..4 { |
157 | | let dec = FixedDecimal::from(1).multiplied_pow10((i as i16) + 3); |
158 | | let provider = AnyPayloadProvider::from_owned::<DecimalSymbolsV1Marker>( |
159 | | crate::provider::DecimalSymbolsV1 { |
160 | | grouping_sizes: cas.sizes, |
161 | | ..Default::default() |
162 | | }, |
163 | | ); |
164 | | let options = options::FixedDecimalFormatterOptions { |
165 | | grouping_strategy: cas.strategy, |
166 | | ..Default::default() |
167 | | }; |
168 | | let fdf = FixedDecimalFormatter::try_new_unstable( |
169 | | &provider.as_downcasting(), |
170 | | &LanguageIdentifier::UND.into(), |
171 | | options, |
172 | | ) |
173 | | .unwrap(); |
174 | | let actual = fdf.format(&dec); |
175 | | assert_writeable_eq!(actual, cas.expected[i], "{:?}", cas); |
176 | | } |
177 | | } |
178 | | } |