/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::builtins::FluentDateTimeOptions; use fluent::types::FluentNumberCurrencyDisplayStyle; use fluent::types::FluentNumberOptions; use fluent::types::FluentNumberStyle; use nsstring::nsCString; pub enum RawNumberFormatter {} #[repr(C)] pub enum FluentNumberStyleRaw { Decimal, Currency, Percent, } impl From for FluentNumberStyleRaw { fn from(input: FluentNumberStyle) -> Self { match input { FluentNumberStyle::Decimal => Self::Decimal, FluentNumberStyle::Currency => Self::Currency, FluentNumberStyle::Percent => Self::Percent, } } } #[repr(C)] #[derive(Clone, Copy)] pub enum FluentNumberCurrencyDisplayStyleRaw { Symbol, Code, Name, } impl From for FluentNumberCurrencyDisplayStyleRaw { fn from(input: FluentNumberCurrencyDisplayStyle) -> Self { match input { FluentNumberCurrencyDisplayStyle::Symbol => Self::Symbol, FluentNumberCurrencyDisplayStyle::Code => Self::Code, FluentNumberCurrencyDisplayStyle::Name => Self::Name, } } } #[repr(C)] pub struct FluentNumberOptionsRaw { pub style: FluentNumberStyleRaw, pub currency: nsCString, pub currency_display: FluentNumberCurrencyDisplayStyleRaw, pub use_grouping: bool, pub minimum_integer_digits: usize, pub minimum_fraction_digits: usize, pub maximum_fraction_digits: usize, pub minimum_significant_digits: isize, pub maximum_significant_digits: isize, } fn get_number_option(val: Option, min: usize, max: usize, default: usize) -> usize { if let Some(val) = val { if val >= min && val <= max { val } else { default } } else { default } } impl From<&FluentNumberOptions> for FluentNumberOptionsRaw { fn from(input: &FluentNumberOptions) -> Self { let currency: nsCString = if let Some(ref currency) = input.currency { currency.into() } else { nsCString::new() }; //XXX: This should be fetched from currency table. let currency_digits = 2; // Keep it aligned with ECMA402 NumberFormat logic. let minfd_default = if input.style == FluentNumberStyle::Currency { currency_digits } else { 0 }; let maxfd_default = match input.style { FluentNumberStyle::Decimal => 3, FluentNumberStyle::Currency => currency_digits, FluentNumberStyle::Percent => 0, }; let minid = get_number_option(input.minimum_integer_digits, 1, 21, 1); let minfd = get_number_option(input.minimum_fraction_digits, 0, 20, minfd_default); let maxfd_actual_default = std::cmp::max(minfd, maxfd_default); let maxfd = get_number_option( input.maximum_fraction_digits, minfd, 20, maxfd_actual_default, ); let (minsd, maxsd) = if input.minimum_significant_digits.is_some() || input.maximum_significant_digits.is_some() { let minsd = get_number_option(input.minimum_significant_digits, 1, 21, 1); let maxsd = get_number_option(input.maximum_significant_digits, minsd, 21, 21); (minsd as isize, maxsd as isize) } else { (-1, -1) }; Self { style: input.style.into(), currency, currency_display: input.currency_display.into(), use_grouping: input.use_grouping, minimum_integer_digits: minid, minimum_fraction_digits: minfd, maximum_fraction_digits: maxfd, minimum_significant_digits: minsd, maximum_significant_digits: maxsd, } } } pub enum RawDateTimeFormatter {} extern "C" { pub fn FluentBuiltInNumberFormatterCreate( locale: &nsCString, options: &FluentNumberOptionsRaw, ) -> *mut RawNumberFormatter; pub fn FluentBuiltInNumberFormatterFormat( formatter: *const RawNumberFormatter, input: f64, out_count: &mut usize, out_capacity: &mut usize, ) -> *mut u8; pub fn FluentBuiltInNumberFormatterDestroy(formatter: *mut RawNumberFormatter); pub fn FluentBuiltInDateTimeFormatterCreate( locale: &nsCString, options: FluentDateTimeOptions, ) -> *mut RawDateTimeFormatter; pub fn FluentBuiltInDateTimeFormatterFormat( formatter: *const RawDateTimeFormatter, input: f64, out_count: &mut u32, ) -> *mut u8; pub fn FluentBuiltInDateTimeFormatterDestroy(formatter: *mut RawDateTimeFormatter); }