use fixed_decimal::{FixedDecimal, Sign};
use icu_decimal::{
options::FixedDecimalFormatterOptions, provider::DecimalSymbolsV2Marker, FixedDecimalFormatter,
};
use icu_plurals::{provider::CardinalV1Marker, PluralRules};
use icu_provider::marker::ErasedMarker;
use icu_provider::prelude::*;
use crate::relativetime::format::FormattedRelativeTime;
use crate::relativetime::options::RelativeTimeFormatterOptions;
use crate::relativetime::provider::*;
pub struct RelativeTimeFormatter {
pub(crate) plural_rules: PluralRules,
pub(crate) rt: DataPayload<ErasedMarker<RelativeTimePatternDataV1<'static>>>,
pub(crate) options: RelativeTimeFormatterOptions,
pub(crate) fixed_decimal_format: FixedDecimalFormatter,
}
macro_rules! constructor {
($unstable: ident, $baked: ident, $any: ident, $buffer: ident, $marker: ty) => {
#[cfg(feature = "compiled_data")]
pub fn $baked(
locale: &DataLocale,
options: RelativeTimeFormatterOptions,
) -> Result<Self, DataError> {
let temp_loc = locale.clone().into_locale();
let plural_rules = PluralRules::try_new_cardinal(temp_loc.into())?;
let fixed_decimal_format = FixedDecimalFormatter::try_new(
locale,
FixedDecimalFormatterOptions::default(),
)?;
let rt: DataResponse<$marker> = crate::provider::Baked
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(locale),
..Default::default()
})?;
let rt = rt.payload.cast();
Ok(RelativeTimeFormatter {
plural_rules,
options,
rt,
fixed_decimal_format,
})
}
icu_provider::gen_any_buffer_data_constructors!(
(locale, options: RelativeTimeFormatterOptions) -> error: DataError,
functions: [
$baked: skip,
$any,
$buffer,
$unstable,
Self,
]
);
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::$baked)]
pub fn $unstable<D>(
provider: &D,
locale: &DataLocale,
options: RelativeTimeFormatterOptions,
) -> Result<Self, DataError>
where
D: DataProvider<CardinalV1Marker>
+ DataProvider<$marker>
+ DataProvider<DecimalSymbolsV2Marker>
+ ?Sized,
{
let temp_loc = locale.clone().into_locale();
let plural_rules = PluralRules::try_new_cardinal_unstable(provider, temp_loc.into())?;
let fixed_decimal_format = FixedDecimalFormatter::try_new_unstable(
provider,
locale,
FixedDecimalFormatterOptions::default(),
)?;
let rt: DataResponse<$marker> = provider
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(locale),
..Default::default()
})?;
let rt = rt.payload.cast();
Ok(RelativeTimeFormatter {
plural_rules,
options,
rt,
fixed_decimal_format,
})
}
};
}
impl RelativeTimeFormatter {
constructor!(
try_new_long_second_unstable,
try_new_long_second,
try_new_long_second_with_any_provider,
try_new_long_second_with_buffer_provider,
LongSecondRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_minute_unstable,
try_new_long_minute,
try_new_long_minute_with_any_provider,
try_new_long_minute_with_buffer_provider,
LongMinuteRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_hour_unstable,
try_new_long_hour,
try_new_long_hour_with_any_provider,
try_new_long_hour_with_buffer_provider,
LongHourRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_day_unstable,
try_new_long_day,
try_new_long_day_with_any_provider,
try_new_long_day_with_buffer_provider,
LongDayRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_week_unstable,
try_new_long_week,
try_new_long_week_with_any_provider,
try_new_long_week_with_buffer_provider,
LongWeekRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_month_unstable,
try_new_long_month,
try_new_long_month_with_any_provider,
try_new_long_month_with_buffer_provider,
LongMonthRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_quarter_unstable,
try_new_long_quarter,
try_new_long_quarter_with_any_provider,
try_new_long_quarter_with_buffer_provider,
LongQuarterRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_long_year_unstable,
try_new_long_year,
try_new_long_year_with_any_provider,
try_new_long_year_with_buffer_provider,
LongYearRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_second_unstable,
try_new_short_second,
try_new_short_second_with_any_provider,
try_new_short_second_with_buffer_provider,
ShortSecondRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_minute_unstable,
try_new_short_minute,
try_new_short_minute_with_any_provider,
try_new_short_minute_with_buffer_provider,
ShortMinuteRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_hour_unstable,
try_new_short_hour,
try_new_short_hour_with_any_provider,
try_new_short_hour_with_buffer_provider,
ShortHourRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_day_unstable,
try_new_short_day,
try_new_short_day_with_any_provider,
try_new_short_day_with_buffer_provider,
ShortDayRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_week_unstable,
try_new_short_week,
try_new_short_week_with_any_provider,
try_new_short_week_with_buffer_provider,
ShortWeekRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_month_unstable,
try_new_short_month,
try_new_short_month_with_any_provider,
try_new_short_month_with_buffer_provider,
ShortMonthRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_quarter_unstable,
try_new_short_quarter,
try_new_short_quarter_with_any_provider,
try_new_short_quarter_with_buffer_provider,
ShortQuarterRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_short_year_unstable,
try_new_short_year,
try_new_short_year_with_any_provider,
try_new_short_year_with_buffer_provider,
ShortYearRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_second_unstable,
try_new_narrow_second,
try_new_narrow_second_with_any_provider,
try_new_narrow_second_with_buffer_provider,
NarrowSecondRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_minute_unstable,
try_new_narrow_minute,
try_new_narrow_minute_with_any_provider,
try_new_narrow_minute_with_buffer_provider,
NarrowMinuteRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_hour_unstable,
try_new_narrow_hour,
try_new_narrow_hour_with_any_provider,
try_new_narrow_hour_with_buffer_provider,
NarrowHourRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_day_unstable,
try_new_narrow_day,
try_new_narrow_day_with_any_provider,
try_new_narrow_day_with_buffer_provider,
NarrowDayRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_week_unstable,
try_new_narrow_week,
try_new_narrow_week_with_any_provider,
try_new_narrow_week_with_buffer_provider,
NarrowWeekRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_month_unstable,
try_new_narrow_month,
try_new_narrow_month_with_any_provider,
try_new_narrow_month_with_buffer_provider,
NarrowMonthRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_quarter_unstable,
try_new_narrow_quarter,
try_new_narrow_quarter_with_any_provider,
try_new_narrow_quarter_with_buffer_provider,
NarrowQuarterRelativeTimeFormatDataV1Marker
);
constructor!(
try_new_narrow_year_unstable,
try_new_narrow_year,
try_new_narrow_year_with_any_provider,
try_new_narrow_year_with_buffer_provider,
NarrowYearRelativeTimeFormatDataV1Marker
);
pub fn format(&self, value: FixedDecimal) -> FormattedRelativeTime<'_> {
let is_negative = value.sign() == Sign::Negative;
FormattedRelativeTime {
options: &self.options,
formatter: self,
value: value.with_sign(Sign::None),
is_negative,
}
}
}