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 ).
5 use fixed_decimal::RoundingIncrement;
6 use fixed_decimal::Sign;
7 use fixed_decimal::SignDisplay;
11 use alloc::boxed::Box;
12 use fixed_decimal::{DoublePrecision, FixedDecimal};
13 use writeable::Writeable;
15 use crate::errors::ffi::ICU4XError;
18 #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)]
19 pub struct ICU4XFixedDecimal(pub FixedDecimal);
21 /// The sign of a FixedDecimal, as shown in formatting.
22 #[diplomat::rust_link(fixed_decimal::Sign, Enum)]
23 pub enum ICU4XFixedDecimalSign {
24 /// No sign (implicitly positive, e.g., 1729).
26 /// A negative sign, e.g., -1729.
28 /// An explicit positive sign, e.g., +1729.
32 /// ECMA-402 compatible sign display preference.
33 #[diplomat::rust_link(fixed_decimal::SignDisplay, Enum)]
34 pub enum ICU4XFixedDecimalSignDisplay {
42 // TODO: Rename to `ICU4XFixedDecimalRoundingIncrement` for 2.0
43 /// Increment used in a rounding operation.
44 #[diplomat::rust_link(fixed_decimal::RoundingIncrement, Enum)]
45 pub enum ICU4XRoundingIncrement {
52 impl ICU4XFixedDecimal {
53 /// Construct an [`ICU4XFixedDecimal`] from an integer.
54 #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)]
55 #[diplomat::attr(dart, disable)]
56 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_i32")]
57 pub fn create_from_i32(v: i32) -> Box<ICU4XFixedDecimal> {
58 Box::new(ICU4XFixedDecimal(FixedDecimal::from(v)))
61 /// Construct an [`ICU4XFixedDecimal`] from an integer.
62 #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)]
63 #[diplomat::attr(dart, disable)]
64 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_u32")]
65 pub fn create_from_u32(v: u32) -> Box<ICU4XFixedDecimal> {
66 Box::new(ICU4XFixedDecimal(FixedDecimal::from(v)))
69 /// Construct an [`ICU4XFixedDecimal`] from an integer.
70 #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)]
71 #[diplomat::attr(dart, rename = "from_int")]
72 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_i64")]
73 pub fn create_from_i64(v: i64) -> Box<ICU4XFixedDecimal> {
74 Box::new(ICU4XFixedDecimal(FixedDecimal::from(v)))
77 /// Construct an [`ICU4XFixedDecimal`] from an integer.
78 #[diplomat::rust_link(fixed_decimal::FixedDecimal, Struct)]
79 #[diplomat::attr(dart, disable)]
80 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_u64")]
81 pub fn create_from_u64(v: u64) -> Box<ICU4XFixedDecimal> {
82 Box::new(ICU4XFixedDecimal(FixedDecimal::from(v)))
85 /// Construct an [`ICU4XFixedDecimal`] from an integer-valued float
86 #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)]
87 #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
88 #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
89 #[diplomat::attr(dart, disable)]
90 #[diplomat::attr(dart, rename = "from_double_with_integer_precision")]
91 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_f64_with_integer_precision")]
92 pub fn create_from_f64_with_integer_precision(
94 ) -> Result<Box<ICU4XFixedDecimal>, ICU4XError> {
95 let precision = DoublePrecision::Integer;
96 Ok(Box::new(ICU4XFixedDecimal(FixedDecimal::try_from_f64(
101 /// Construct an [`ICU4XFixedDecimal`] from an float, with a given power of 10 for the lower magnitude
102 #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)]
103 #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
104 #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
105 #[diplomat::attr(dart, rename = "from_double_with_lower_magnitude")]
106 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_f64_with_lower_magnitude")]
107 pub fn create_from_f64_with_lower_magnitude(
110 ) -> Result<Box<ICU4XFixedDecimal>, ICU4XError> {
111 let precision = DoublePrecision::Magnitude(magnitude);
112 Ok(Box::new(ICU4XFixedDecimal(FixedDecimal::try_from_f64(
117 /// Construct an [`ICU4XFixedDecimal`] from an float, for a given number of significant digits
118 #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)]
119 #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
120 #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
121 #[diplomat::attr(dart, rename = "from_double_with_significant_digits")]
122 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_f64_with_significant_digits")]
123 pub fn create_from_f64_with_significant_digits(
126 ) -> Result<Box<ICU4XFixedDecimal>, ICU4XError> {
127 let precision = DoublePrecision::SignificantDigits(digits);
128 Ok(Box::new(ICU4XFixedDecimal(FixedDecimal::try_from_f64(
133 /// Construct an [`ICU4XFixedDecimal`] from an float, with enough digits to recover
134 /// the original floating point in IEEE 754 without needing trailing zeros
135 #[diplomat::rust_link(fixed_decimal::FixedDecimal::try_from_f64, FnInStruct)]
136 #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
137 #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
138 #[diplomat::attr(dart, rename = "from_double_with_double_precision")]
139 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_f64_with_floating_precision")]
140 pub fn create_from_f64_with_floating_precision(
142 ) -> Result<Box<ICU4XFixedDecimal>, ICU4XError> {
143 let precision = DoublePrecision::Floating;
144 Ok(Box::new(ICU4XFixedDecimal(FixedDecimal::try_from_f64(
149 /// Construct an [`ICU4XFixedDecimal`] from a string.
150 #[diplomat::rust_link(fixed_decimal::FixedDecimal::from_str, FnInStruct)]
151 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_string")]
152 pub fn create_from_string(v: &DiplomatStr) -> Result<Box<ICU4XFixedDecimal>, ICU4XError> {
153 Ok(Box::new(ICU4XFixedDecimal(FixedDecimal::try_from(v)?)))
156 #[diplomat::rust_link(fixed_decimal::FixedDecimal::digit_at, FnInStruct)]
157 pub fn digit_at(&self, magnitude: i16) -> u8 {
158 self.0.digit_at(magnitude)
161 #[diplomat::rust_link(fixed_decimal::FixedDecimal::magnitude_range, FnInStruct)]
162 #[diplomat::attr(supports = accessors, getter)]
163 pub fn magnitude_start(&self) -> i16 {
164 *self.0.magnitude_range().start()
167 #[diplomat::rust_link(fixed_decimal::FixedDecimal::magnitude_range, FnInStruct)]
168 #[diplomat::attr(supports = accessors, getter)]
169 pub fn magnitude_end(&self) -> i16 {
170 *self.0.magnitude_range().end()
173 #[diplomat::rust_link(fixed_decimal::FixedDecimal::nonzero_magnitude_start, FnInStruct)]
174 #[diplomat::attr(supports = accessors, getter)]
175 pub fn nonzero_magnitude_start(&self) -> i16 {
176 self.0.nonzero_magnitude_start()
179 #[diplomat::rust_link(fixed_decimal::FixedDecimal::nonzero_magnitude_end, FnInStruct)]
180 #[diplomat::attr(supports = accessors, getter)]
181 pub fn nonzero_magnitude_end(&self) -> i16 {
182 self.0.nonzero_magnitude_end()
185 #[diplomat::rust_link(fixed_decimal::FixedDecimal::is_zero, FnInStruct)]
186 #[diplomat::attr(supports = accessors, getter)]
187 pub fn is_zero(&self) -> bool {
191 /// Multiply the [`ICU4XFixedDecimal`] by a given power of ten.
192 #[diplomat::rust_link(fixed_decimal::FixedDecimal::multiply_pow10, FnInStruct)]
193 #[diplomat::rust_link(fixed_decimal::FixedDecimal::multiplied_pow10, FnInStruct, hidden)]
194 pub fn multiply_pow10(&mut self, power: i16) {
195 self.0.multiply_pow10(power)
198 #[diplomat::rust_link(fixed_decimal::FixedDecimal::sign, FnInStruct)]
199 #[diplomat::attr(supports = accessors, getter)]
200 pub fn sign(&self) -> ICU4XFixedDecimalSign {
204 /// Set the sign of the [`ICU4XFixedDecimal`].
205 #[diplomat::rust_link(fixed_decimal::FixedDecimal::set_sign, FnInStruct)]
206 #[diplomat::rust_link(fixed_decimal::FixedDecimal::with_sign, FnInStruct, hidden)]
207 #[diplomat::attr(supports = accessors, setter = "sign")]
208 pub fn set_sign(&mut self, sign: ICU4XFixedDecimalSign) {
209 self.0.set_sign(sign.into())
212 #[diplomat::rust_link(fixed_decimal::FixedDecimal::apply_sign_display, FnInStruct)]
213 #[diplomat::rust_link(fixed_decimal::FixedDecimal::with_sign_display, FnInStruct, hidden)]
214 pub fn apply_sign_display(&mut self, sign_display: ICU4XFixedDecimalSignDisplay) {
215 self.0.apply_sign_display(sign_display.into())
218 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trim_start, FnInStruct)]
219 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trimmed_start, FnInStruct, hidden)]
220 pub fn trim_start(&mut self) {
224 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trim_end, FnInStruct)]
225 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trimmed_end, FnInStruct, hidden)]
226 pub fn trim_end(&mut self) {
230 /// Zero-pad the [`ICU4XFixedDecimal`] on the left to a particular position
231 #[diplomat::rust_link(fixed_decimal::FixedDecimal::pad_start, FnInStruct)]
232 #[diplomat::rust_link(fixed_decimal::FixedDecimal::padded_start, FnInStruct, hidden)]
233 pub fn pad_start(&mut self, position: i16) {
234 self.0.pad_start(position)
237 /// Zero-pad the [`ICU4XFixedDecimal`] on the right to a particular position
238 #[diplomat::rust_link(fixed_decimal::FixedDecimal::pad_end, FnInStruct)]
239 #[diplomat::rust_link(fixed_decimal::FixedDecimal::padded_end, FnInStruct, hidden)]
240 pub fn pad_end(&mut self, position: i16) {
241 self.0.pad_end(position)
244 /// Truncate the [`ICU4XFixedDecimal`] on the left to a particular position, deleting digits if necessary. This is useful for, e.g. abbreviating years
246 #[diplomat::rust_link(fixed_decimal::FixedDecimal::set_max_position, FnInStruct)]
247 #[diplomat::rust_link(fixed_decimal::FixedDecimal::with_max_position, FnInStruct, hidden)]
248 pub fn set_max_position(&mut self, position: i16) {
249 self.0.set_max_position(position)
252 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trunc, FnInStruct)]
253 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trunced, FnInStruct, hidden)]
254 pub fn trunc(&mut self, position: i16) {
255 self.0.trunc(position)
258 #[diplomat::rust_link(fixed_decimal::FixedDecimal::trunc_to_increment, FnInStruct)]
259 #[diplomat::rust_link(
260 fixed_decimal::FixedDecimal::trunced_to_increment,
264 pub fn trunc_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) {
265 self.0.trunc_to_increment(position, increment.into())
268 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_trunc, FnInStruct)]
269 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_trunced, FnInStruct, hidden)]
270 pub fn half_trunc(&mut self, position: i16) {
271 self.0.half_trunc(position)
274 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_trunc_to_increment, FnInStruct)]
275 #[diplomat::rust_link(
276 fixed_decimal::FixedDecimal::half_trunced_to_increment,
280 pub fn half_trunc_to_increment(
283 increment: ICU4XRoundingIncrement,
285 self.0.half_trunc_to_increment(position, increment.into())
288 #[diplomat::rust_link(fixed_decimal::FixedDecimal::expand, FnInStruct)]
289 #[diplomat::rust_link(fixed_decimal::FixedDecimal::expanded, FnInStruct, hidden)]
290 pub fn expand(&mut self, position: i16) {
291 self.0.expand(position)
294 #[diplomat::rust_link(fixed_decimal::FixedDecimal::expand_to_increment, FnInStruct)]
295 #[diplomat::rust_link(
296 fixed_decimal::FixedDecimal::expanded_to_increment,
300 pub fn expand_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) {
301 self.0.expand_to_increment(position, increment.into())
304 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_expand, FnInStruct)]
305 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_expanded, FnInStruct, hidden)]
306 pub fn half_expand(&mut self, position: i16) {
307 self.0.half_expand(position)
310 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_expand_to_increment, FnInStruct)]
311 #[diplomat::rust_link(
312 fixed_decimal::FixedDecimal::half_expanded_to_increment,
316 pub fn half_expand_to_increment(
319 increment: ICU4XRoundingIncrement,
321 self.0.half_expand_to_increment(position, increment.into())
324 #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceil, FnInStruct)]
325 #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceiled, FnInStruct, hidden)]
326 pub fn ceil(&mut self, position: i16) {
327 self.0.ceil(position)
330 #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceil_to_increment, FnInStruct)]
331 #[diplomat::rust_link(fixed_decimal::FixedDecimal::ceiled_to_increment, FnInStruct, hidden)]
332 pub fn ceil_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) {
333 self.0.ceil_to_increment(position, increment.into())
336 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_ceil, FnInStruct)]
337 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_ceiled, FnInStruct, hidden)]
338 pub fn half_ceil(&mut self, position: i16) {
339 self.0.half_ceil(position)
342 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_ceil_to_increment, FnInStruct)]
343 #[diplomat::rust_link(
344 fixed_decimal::FixedDecimal::half_ceiled_to_increment,
348 pub fn half_ceil_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) {
349 self.0.half_ceil_to_increment(position, increment.into())
352 #[diplomat::rust_link(fixed_decimal::FixedDecimal::floor, FnInStruct)]
353 #[diplomat::rust_link(fixed_decimal::FixedDecimal::floored, FnInStruct, hidden)]
354 pub fn floor(&mut self, position: i16) {
355 self.0.floor(position)
358 #[diplomat::rust_link(fixed_decimal::FixedDecimal::floor_to_increment, FnInStruct)]
359 #[diplomat::rust_link(
360 fixed_decimal::FixedDecimal::floored_to_increment,
364 pub fn floor_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) {
365 self.0.floor_to_increment(position, increment.into())
368 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_floor, FnInStruct)]
369 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_floored, FnInStruct, hidden)]
370 pub fn half_floor(&mut self, position: i16) {
371 self.0.half_floor(position)
374 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_floor_to_increment, FnInStruct)]
375 #[diplomat::rust_link(
376 fixed_decimal::FixedDecimal::half_floored_to_increment,
380 pub fn half_floor_to_increment(
383 increment: ICU4XRoundingIncrement,
385 self.0.half_floor_to_increment(position, increment.into())
388 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_even, FnInStruct)]
389 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_evened, FnInStruct, hidden)]
390 pub fn half_even(&mut self, position: i16) {
391 self.0.half_even(position)
394 #[diplomat::rust_link(fixed_decimal::FixedDecimal::half_even_to_increment, FnInStruct)]
395 #[diplomat::rust_link(
396 fixed_decimal::FixedDecimal::half_evened_to_increment,
400 pub fn half_even_to_increment(&mut self, position: i16, increment: ICU4XRoundingIncrement) {
401 self.0.half_even_to_increment(position, increment.into())
404 /// Concatenates `other` to the end of `self`.
406 /// If successful, `other` will be set to 0 and a successful status is returned.
408 /// If not successful, `other` will be unchanged and an error is returned.
409 #[diplomat::rust_link(fixed_decimal::FixedDecimal::concatenate_end, FnInStruct)]
410 #[diplomat::rust_link(fixed_decimal::FixedDecimal::concatenated_end, FnInStruct, hidden)]
411 pub fn concatenate_end(&mut self, other: &mut ICU4XFixedDecimal) -> Result<(), ()> {
412 let x = core::mem::take(&mut other.0);
413 self.0.concatenate_end(x).map_err(|y| {
418 /// Format the [`ICU4XFixedDecimal`] as a string.
419 #[diplomat::rust_link(fixed_decimal::FixedDecimal::write_to, FnInStruct)]
420 #[diplomat::attr(supports = stringifiers, stringifier)]
421 pub fn to_string(&self, to: &mut diplomat_runtime::DiplomatWriteable) {
422 let _ = self.0.write_to(to);
427 impl From<ffi::ICU4XFixedDecimalSign> for Sign {
428 fn from(other: ffi::ICU4XFixedDecimalSign) -> Self {
430 ffi::ICU4XFixedDecimalSign::None => Self::None,
431 ffi::ICU4XFixedDecimalSign::Negative => Self::Negative,
432 ffi::ICU4XFixedDecimalSign::Positive => Self::Positive,
437 impl From<Sign> for ffi::ICU4XFixedDecimalSign {
438 fn from(other: Sign) -> Self {
440 Sign::None => Self::None,
441 Sign::Negative => Self::Negative,
442 Sign::Positive => Self::Positive,
447 impl From<ffi::ICU4XFixedDecimalSignDisplay> for SignDisplay {
448 fn from(other: ffi::ICU4XFixedDecimalSignDisplay) -> Self {
450 ffi::ICU4XFixedDecimalSignDisplay::Auto => Self::Auto,
451 ffi::ICU4XFixedDecimalSignDisplay::Never => Self::Never,
452 ffi::ICU4XFixedDecimalSignDisplay::Always => Self::Always,
453 ffi::ICU4XFixedDecimalSignDisplay::ExceptZero => Self::ExceptZero,
454 ffi::ICU4XFixedDecimalSignDisplay::Negative => Self::Negative,
459 impl From<ffi::ICU4XRoundingIncrement> for RoundingIncrement {
460 fn from(value: ffi::ICU4XRoundingIncrement) -> Self {
462 ffi::ICU4XRoundingIncrement::MultiplesOf1 => RoundingIncrement::MultiplesOf1,
463 ffi::ICU4XRoundingIncrement::MultiplesOf2 => RoundingIncrement::MultiplesOf2,
464 ffi::ICU4XRoundingIncrement::MultiplesOf5 => RoundingIncrement::MultiplesOf5,
465 ffi::ICU4XRoundingIncrement::MultiplesOf25 => RoundingIncrement::MultiplesOf25,