tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fixed_decimal.rs (17479B)


      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 use ffi::DecimalSignedRoundingMode;
      6 
      7 #[diplomat::bridge]
      8 #[diplomat::abi_rename = "icu4x_{0}_mv1"]
      9 #[diplomat::attr(auto, namespace = "icu4x")]
     10 pub mod ffi {
     11    use alloc::boxed::Box;
     12 
     13    use crate::unstable::errors::ffi::{DecimalLimitError, DecimalParseError};
     14 
     15    use writeable::Writeable;
     16 
     17    #[diplomat::opaque]
     18    #[diplomat::rust_link(fixed_decimal::Decimal, Typedef)]
     19    pub struct Decimal(pub fixed_decimal::Decimal);
     20 
     21    /// The sign of a Decimal, as shown in formatting.
     22    #[diplomat::rust_link(fixed_decimal::Sign, Enum)]
     23    #[diplomat::enum_convert(fixed_decimal::Sign, needs_wildcard)]
     24    pub enum DecimalSign {
     25        /// No sign (implicitly positive, e.g., 1729).
     26        None,
     27        /// A negative sign, e.g., -1729.
     28        Negative,
     29        /// An explicit positive sign, e.g., +1729.
     30        Positive,
     31    }
     32 
     33    /// ECMA-402 compatible sign display preference.
     34    #[diplomat::rust_link(fixed_decimal::SignDisplay, Enum)]
     35    #[diplomat::enum_convert(fixed_decimal::SignDisplay, needs_wildcard)]
     36    pub enum DecimalSignDisplay {
     37        Auto,
     38        Never,
     39        Always,
     40        ExceptZero,
     41        Negative,
     42    }
     43 
     44    /// Increment used in a rounding operation.
     45    #[diplomat::rust_link(fixed_decimal::RoundingIncrement, Enum)]
     46    #[diplomat::enum_convert(fixed_decimal::RoundingIncrement, needs_wildcard)]
     47    pub enum DecimalRoundingIncrement {
     48        MultiplesOf1,
     49        MultiplesOf2,
     50        MultiplesOf5,
     51        MultiplesOf25,
     52    }
     53 
     54    /// Mode used in a rounding operation for signed numbers.
     55    #[diplomat::rust_link(fixed_decimal::SignedRoundingMode, Enum)]
     56    pub enum DecimalSignedRoundingMode {
     57        Expand,
     58        Trunc,
     59        HalfExpand,
     60        HalfTrunc,
     61        HalfEven,
     62        Ceil,
     63        Floor,
     64        HalfCeil,
     65        HalfFloor,
     66    }
     67 
     68    impl Decimal {
     69        /// Construct an [`Decimal`] from an integer.
     70        #[diplomat::rust_link(fixed_decimal::Decimal, Struct)]
     71        #[diplomat::attr(dart, disable)]
     72        #[diplomat::attr(js, rename = "from_number")]
     73        #[diplomat::attr(supports = method_overloading, rename = "from")]
     74        #[diplomat::attr(auto, named_constructor)]
     75        pub fn from_int32(v: i32) -> Box<Decimal> {
     76            Box::new(Decimal(fixed_decimal::Decimal::from(v)))
     77        }
     78 
     79        /// Construct an [`Decimal`] from an integer.
     80        #[diplomat::rust_link(fixed_decimal::Decimal, Struct)]
     81        #[diplomat::attr(dart, disable)]
     82        #[diplomat::attr(js, disable)]
     83        #[diplomat::attr(supports = method_overloading, rename = "from")]
     84        #[diplomat::attr(auto, named_constructor)]
     85        pub fn from_uint32(v: u32) -> Box<Decimal> {
     86            Box::new(Decimal(fixed_decimal::Decimal::from(v)))
     87        }
     88 
     89        /// Construct an [`Decimal`] from an integer.
     90        #[diplomat::rust_link(fixed_decimal::Decimal, Struct)]
     91        #[diplomat::attr(dart, rename = "from_int")]
     92        #[diplomat::attr(js, rename = "from_big_int")]
     93        #[diplomat::attr(supports = method_overloading, rename = "from")]
     94        #[diplomat::attr(auto, named_constructor)]
     95        pub fn from_int64(v: i64) -> Box<Decimal> {
     96            Box::new(Decimal(fixed_decimal::Decimal::from(v)))
     97        }
     98 
     99        /// Construct an [`Decimal`] from an integer.
    100        #[diplomat::rust_link(fixed_decimal::Decimal, Struct)]
    101        #[diplomat::attr(any(dart, js), disable)]
    102        #[diplomat::attr(supports = method_overloading, rename = "from")]
    103        #[diplomat::attr(auto, named_constructor)]
    104        pub fn from_uint64(v: u64) -> Box<Decimal> {
    105            Box::new(Decimal(fixed_decimal::Decimal::from(v)))
    106        }
    107 
    108        /// Construct an [`Decimal`] from an integer-valued float
    109        #[diplomat::rust_link(fixed_decimal::Decimal::try_from_f64, FnInTypedef)]
    110        #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
    111        #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
    112        #[diplomat::attr(any(dart, js), disable)]
    113        #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
    114        pub fn from_double_with_integer_precision(
    115            f: f64,
    116        ) -> Result<Box<Decimal>, DecimalLimitError> {
    117            let precision = fixed_decimal::DoublePrecision::Integer;
    118            Ok(Box::new(Decimal(fixed_decimal::Decimal::try_from_f64(
    119                f, precision,
    120            )?)))
    121        }
    122 
    123        /// Construct an [`Decimal`] from an float, with a given power of 10 for the lower magnitude
    124        #[diplomat::rust_link(fixed_decimal::Decimal::try_from_f64, FnInTypedef)]
    125        #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
    126        #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
    127        #[diplomat::attr(js, rename = "from_number_with_lower_magnitude")]
    128        #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
    129        pub fn from_double_with_lower_magnitude(
    130            f: f64,
    131            magnitude: i16,
    132        ) -> Result<Box<Decimal>, DecimalLimitError> {
    133            let precision = fixed_decimal::DoublePrecision::Magnitude(magnitude);
    134            Ok(Box::new(Decimal(fixed_decimal::Decimal::try_from_f64(
    135                f, precision,
    136            )?)))
    137        }
    138 
    139        /// Construct an [`Decimal`] from an float, for a given number of significant digits
    140        #[diplomat::rust_link(fixed_decimal::Decimal::try_from_f64, FnInTypedef)]
    141        #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
    142        #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
    143        #[diplomat::attr(js, rename = "from_number_with_significant_digits")]
    144        #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
    145        pub fn from_double_with_significant_digits(
    146            f: f64,
    147            digits: u8,
    148        ) -> Result<Box<Decimal>, DecimalLimitError> {
    149            let precision = fixed_decimal::DoublePrecision::SignificantDigits(digits);
    150            Ok(Box::new(Decimal(fixed_decimal::Decimal::try_from_f64(
    151                f, precision,
    152            )?)))
    153        }
    154 
    155        /// Construct an [`Decimal`] from an float, with enough digits to recover
    156        /// the original floating point in IEEE 754 without needing trailing zeros
    157        #[diplomat::rust_link(fixed_decimal::Decimal::try_from_f64, FnInTypedef)]
    158        #[diplomat::rust_link(fixed_decimal::FloatPrecision, Enum)]
    159        #[diplomat::rust_link(fixed_decimal::DoublePrecision, Enum, hidden)]
    160        #[diplomat::attr(js, rename = "from_number_with_round_trip_precision")]
    161        #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
    162        #[diplomat::demo(default_constructor)]
    163        pub fn from_double_with_round_trip_precision(
    164            f: f64,
    165        ) -> Result<Box<Decimal>, DecimalLimitError> {
    166            let precision = fixed_decimal::DoublePrecision::RoundTrip;
    167            Ok(Box::new(Decimal(fixed_decimal::Decimal::try_from_f64(
    168                f, precision,
    169            )?)))
    170        }
    171 
    172        /// Construct an [`Decimal`] from a string.
    173        #[diplomat::rust_link(fixed_decimal::Decimal::try_from_str, FnInTypedef)]
    174        #[diplomat::rust_link(fixed_decimal::Decimal::try_from_utf8, FnInTypedef, hidden)]
    175        #[diplomat::rust_link(fixed_decimal::Decimal::from_str, FnInTypedef, hidden)]
    176        #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
    177        pub fn from_string(v: &DiplomatStr) -> Result<Box<Decimal>, DecimalParseError> {
    178            Ok(Box::new(Decimal(fixed_decimal::Decimal::try_from_utf8(v)?)))
    179        }
    180 
    181        #[diplomat::rust_link(fixed_decimal::Decimal::digit_at, FnInTypedef)]
    182        pub fn digit_at(&self, magnitude: i16) -> u8 {
    183            self.0.absolute.digit_at(magnitude)
    184        }
    185 
    186        #[diplomat::rust_link(fixed_decimal::Decimal::magnitude_range, FnInTypedef)]
    187        #[diplomat::attr(auto, getter)]
    188        pub fn magnitude_start(&self) -> i16 {
    189            *self.0.absolute.magnitude_range().start()
    190        }
    191 
    192        #[diplomat::rust_link(fixed_decimal::Decimal::magnitude_range, FnInTypedef)]
    193        #[diplomat::attr(auto, getter)]
    194        pub fn magnitude_end(&self) -> i16 {
    195            *self.0.absolute.magnitude_range().end()
    196        }
    197 
    198        #[diplomat::rust_link(fixed_decimal::Decimal::nonzero_magnitude_start, FnInTypedef)]
    199        #[diplomat::attr(auto, getter)]
    200        pub fn nonzero_magnitude_start(&self) -> i16 {
    201            self.0.absolute.nonzero_magnitude_start()
    202        }
    203 
    204        #[diplomat::rust_link(fixed_decimal::Decimal::nonzero_magnitude_end, FnInTypedef)]
    205        #[diplomat::attr(auto, getter)]
    206        pub fn nonzero_magnitude_end(&self) -> i16 {
    207            self.0.absolute.nonzero_magnitude_end()
    208        }
    209 
    210        #[diplomat::rust_link(fixed_decimal::Decimal::is_zero, FnInTypedef)]
    211        #[diplomat::attr(auto, getter)]
    212        pub fn is_zero(&self) -> bool {
    213            self.0.absolute.is_zero()
    214        }
    215 
    216        /// Multiply the [`Decimal`] by a given power of ten.
    217        #[diplomat::rust_link(fixed_decimal::Decimal::multiply_pow10, FnInTypedef)]
    218        #[diplomat::rust_link(fixed_decimal::Decimal::multiplied_pow10, FnInTypedef, hidden)]
    219        pub fn multiply_pow10(&mut self, power: i16) {
    220            self.0.multiply_pow10(power)
    221        }
    222 
    223        #[diplomat::rust_link(fixed_decimal::Decimal::sign, FnInTypedef)]
    224        #[diplomat::attr(auto, getter)]
    225        pub fn sign(&self) -> DecimalSign {
    226            self.0.sign().into()
    227        }
    228 
    229        /// Set the sign of the [`Decimal`].
    230        #[diplomat::rust_link(fixed_decimal::Decimal::set_sign, FnInTypedef)]
    231        #[diplomat::rust_link(fixed_decimal::Decimal::with_sign, FnInTypedef, hidden)]
    232        #[diplomat::attr(auto, setter = "sign")]
    233        pub fn set_sign(&mut self, sign: DecimalSign) {
    234            self.0.set_sign(sign.into())
    235        }
    236 
    237        #[diplomat::rust_link(fixed_decimal::Decimal::apply_sign_display, FnInTypedef)]
    238        #[diplomat::rust_link(fixed_decimal::Decimal::with_sign_display, FnInTypedef, hidden)]
    239        pub fn apply_sign_display(&mut self, sign_display: DecimalSignDisplay) {
    240            self.0.apply_sign_display(sign_display.into())
    241        }
    242 
    243        #[diplomat::rust_link(fixed_decimal::Decimal::trim_start, FnInTypedef)]
    244        #[diplomat::rust_link(fixed_decimal::Decimal::trimmed_start, FnInTypedef, hidden)]
    245        pub fn trim_start(&mut self) {
    246            self.0.absolute.trim_start()
    247        }
    248 
    249        #[diplomat::rust_link(fixed_decimal::Decimal::trim_end, FnInTypedef)]
    250        #[diplomat::rust_link(fixed_decimal::Decimal::trimmed_end, FnInTypedef, hidden)]
    251        pub fn trim_end(&mut self) {
    252            self.0.absolute.trim_end()
    253        }
    254 
    255        #[diplomat::rust_link(fixed_decimal::Decimal::trim_end_if_integer, FnInTypedef)]
    256        #[diplomat::rust_link(fixed_decimal::Decimal::trimmed_end_if_integer, FnInTypedef, hidden)]
    257        pub fn trim_end_if_integer(&mut self) {
    258            self.0.absolute.trim_end_if_integer()
    259        }
    260 
    261        /// Zero-pad the [`Decimal`] on the left to a particular position
    262        #[diplomat::rust_link(fixed_decimal::Decimal::pad_start, FnInTypedef)]
    263        #[diplomat::rust_link(fixed_decimal::Decimal::padded_start, FnInTypedef, hidden)]
    264        pub fn pad_start(&mut self, position: i16) {
    265            self.0.absolute.pad_start(position)
    266        }
    267 
    268        /// Zero-pad the [`Decimal`] on the right to a particular position
    269        #[diplomat::rust_link(fixed_decimal::Decimal::pad_end, FnInTypedef)]
    270        #[diplomat::rust_link(fixed_decimal::Decimal::padded_end, FnInTypedef, hidden)]
    271        pub fn pad_end(&mut self, position: i16) {
    272            self.0.absolute.pad_end(position)
    273        }
    274 
    275        /// Truncate the [`Decimal`] on the left to a particular position, deleting digits if necessary. This is useful for, e.g. abbreviating years
    276        /// ("2022" -> "22")
    277        #[diplomat::rust_link(fixed_decimal::Decimal::set_max_position, FnInTypedef)]
    278        #[diplomat::rust_link(fixed_decimal::Decimal::with_max_position, FnInTypedef, hidden)]
    279        pub fn set_max_position(&mut self, position: i16) {
    280            self.0.absolute.set_max_position(position)
    281        }
    282 
    283        /// Round the number at a particular digit position.
    284        ///
    285        /// This uses half to even rounding, which resolves ties by selecting the nearest
    286        /// even integer to the original value.
    287        #[diplomat::rust_link(fixed_decimal::Decimal::round, FnInTypedef)]
    288        #[diplomat::rust_link(fixed_decimal::Decimal::rounded, FnInTypedef, hidden)]
    289        pub fn round(&mut self, position: i16) {
    290            self.0.round(position)
    291        }
    292 
    293        #[diplomat::rust_link(fixed_decimal::Decimal::ceil, FnInTypedef)]
    294        #[diplomat::rust_link(fixed_decimal::Decimal::ceiled, FnInTypedef, hidden)]
    295        pub fn ceil(&mut self, position: i16) {
    296            self.0.ceil(position)
    297        }
    298 
    299        #[diplomat::rust_link(fixed_decimal::Decimal::expand, FnInTypedef)]
    300        #[diplomat::rust_link(fixed_decimal::Decimal::expanded, FnInTypedef, hidden)]
    301        pub fn expand(&mut self, position: i16) {
    302            self.0.expand(position)
    303        }
    304 
    305        #[diplomat::rust_link(fixed_decimal::Decimal::floor, FnInTypedef)]
    306        #[diplomat::rust_link(fixed_decimal::Decimal::floored, FnInTypedef, hidden)]
    307        pub fn floor(&mut self, position: i16) {
    308            self.0.floor(position)
    309        }
    310 
    311        #[diplomat::rust_link(fixed_decimal::Decimal::trunc, FnInTypedef)]
    312        #[diplomat::rust_link(fixed_decimal::Decimal::trunced, FnInTypedef, hidden)]
    313        pub fn trunc(&mut self, position: i16) {
    314            self.0.trunc(position)
    315        }
    316 
    317        #[diplomat::rust_link(fixed_decimal::Decimal::round_with_mode, FnInTypedef)]
    318        #[diplomat::rust_link(fixed_decimal::Decimal::rounded_with_mode, FnInTypedef, hidden)]
    319        pub fn round_with_mode(&mut self, position: i16, mode: DecimalSignedRoundingMode) {
    320            self.0.round_with_mode(position, mode.into())
    321        }
    322 
    323        #[diplomat::rust_link(fixed_decimal::Decimal::round_with_mode_and_increment, FnInTypedef)]
    324        #[diplomat::rust_link(
    325            fixed_decimal::Decimal::rounded_with_mode_and_increment,
    326            FnInTypedef,
    327            hidden
    328        )]
    329        pub fn round_with_mode_and_increment(
    330            &mut self,
    331            position: i16,
    332            mode: DecimalSignedRoundingMode,
    333            increment: DecimalRoundingIncrement,
    334        ) {
    335            self.0
    336                .round_with_mode_and_increment(position, mode.into(), increment.into())
    337        }
    338 
    339        /// Concatenates `other` to the end of `self`.
    340        ///
    341        /// If successful, `other` will be set to 0 and a successful status is returned.
    342        ///
    343        /// If not successful, `other` will be unchanged and an error is returned.
    344        #[diplomat::rust_link(fixed_decimal::Decimal::concatenate_end, FnInTypedef)]
    345        #[diplomat::rust_link(fixed_decimal::Decimal::concatenated_end, FnInTypedef, hidden)]
    346        pub fn concatenate_end(&mut self, other: &mut Decimal) -> Result<(), ()> {
    347            let x = core::mem::take(&mut other.0);
    348            self.0.absolute.concatenate_end(x.absolute).map_err(|y| {
    349                other.0.absolute = y;
    350            })
    351        }
    352 
    353        /// Format the [`Decimal`] as a string.
    354        #[diplomat::rust_link(fixed_decimal::Decimal::write_to, FnInTypedef)]
    355        #[diplomat::rust_link(fixed_decimal::Decimal::to_string, FnInTypedef, hidden)]
    356        #[diplomat::attr(auto, stringifier)]
    357        pub fn to_string(&self, to: &mut diplomat_runtime::DiplomatWrite) {
    358            let _ = self.0.write_to(to);
    359        }
    360    }
    361 }
    362 
    363 impl From<DecimalSignedRoundingMode> for fixed_decimal::SignedRoundingMode {
    364    fn from(mode: DecimalSignedRoundingMode) -> Self {
    365        match mode {
    366            DecimalSignedRoundingMode::Expand => fixed_decimal::SignedRoundingMode::Unsigned(
    367                fixed_decimal::UnsignedRoundingMode::Expand,
    368            ),
    369            DecimalSignedRoundingMode::Trunc => fixed_decimal::SignedRoundingMode::Unsigned(
    370                fixed_decimal::UnsignedRoundingMode::Trunc,
    371            ),
    372            DecimalSignedRoundingMode::HalfExpand => fixed_decimal::SignedRoundingMode::Unsigned(
    373                fixed_decimal::UnsignedRoundingMode::HalfExpand,
    374            ),
    375            DecimalSignedRoundingMode::HalfTrunc => fixed_decimal::SignedRoundingMode::Unsigned(
    376                fixed_decimal::UnsignedRoundingMode::HalfTrunc,
    377            ),
    378            DecimalSignedRoundingMode::HalfEven => fixed_decimal::SignedRoundingMode::Unsigned(
    379                fixed_decimal::UnsignedRoundingMode::HalfEven,
    380            ),
    381            DecimalSignedRoundingMode::Ceil => fixed_decimal::SignedRoundingMode::Ceil,
    382            DecimalSignedRoundingMode::Floor => fixed_decimal::SignedRoundingMode::Floor,
    383            DecimalSignedRoundingMode::HalfCeil => fixed_decimal::SignedRoundingMode::HalfCeil,
    384            DecimalSignedRoundingMode::HalfFloor => fixed_decimal::SignedRoundingMode::HalfFloor,
    385        }
    386    }
    387 }