#![allow(clippy::exhaustive_structs)]
#![allow(clippy::exhaustive_enums)]
#[cfg(any(feature = "datagen", feature = "serde"))]
#[cfg(feature = "unstable")]
use alloc::boxed::Box;
#[cfg(feature = "datagen")]
#[cfg(feature = "unstable")]
use alloc::vec::Vec;
#[cfg(feature = "unstable")]
use icu_pattern::{Pattern, PatternBackend, SinglePlaceholder};
#[cfg(feature = "unstable")]
use icu_plurals::provider::PluralElementsPackedULE;
use icu_provider::prelude::*;
#[cfg(feature = "unstable")]
use zerovec::ule::vartuple::VarTupleULE;
use zerovec::VarZeroCow;
#[cfg(feature = "unstable")]
use zerovec::VarZeroVec;
#[cfg(feature = "compiled_data")]
#[derive(Debug)]
pub struct Baked;
#[cfg(feature = "compiled_data")]
#[allow(unused_imports)]
const _: () = {
use icu_decimal_data::*;
pub mod icu {
pub use crate as decimal;
pub use icu_locale as locale;
}
make_provider!(Baked);
#[cfg(feature = "unstable")]
impl_decimal_compact_long_v1!(Baked);
#[cfg(feature = "unstable")]
impl_decimal_compact_short_v1!(Baked);
impl_decimal_symbols_v1!(Baked);
impl_decimal_digits_v1!(Baked);
};
icu_provider::data_marker!(
DecimalSymbolsV1,
"decimal/symbols/v1",
DecimalSymbols<'static>,
);
icu_provider::data_marker!(
DecimalDigitsV1,
"decimal/digits/v1",
[char; 10],
#[cfg(feature = "datagen")]
attributes_domain = "numbering_system"
);
#[cfg(feature = "datagen")]
#[cfg(feature = "unstable")]
pub const MARKERS: &[DataMarkerInfo] = &[
DecimalSymbolsV1::INFO,
DecimalDigitsV1::INFO,
DecimalCompactLongV1::INFO,
DecimalCompactShortV1::INFO,
];
#[cfg(feature = "datagen")]
#[cfg(not(feature = "unstable"))]
pub const MARKERS: &[DataMarkerInfo] = &[DecimalSymbolsV1::INFO, DecimalDigitsV1::INFO];
#[derive(Debug, PartialEq, Clone, yoke::Yokeable, Copy, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_decimal::provider))]
pub struct GroupingSizes {
pub primary: u8,
pub secondary: u8,
pub min_grouping: u8,
}
#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "datagen", derive(serde::Serialize))]
#[zerovec::make_varule(DecimalSymbolsStrs)]
#[zerovec::derive(Debug)]
#[zerovec::skip_derive(Ord)]
#[cfg_attr(not(feature = "alloc"), zerovec::skip_derive(ZeroMapKV, ToOwned))]
#[cfg_attr(feature = "serde", zerovec::derive(Deserialize))]
#[cfg_attr(feature = "datagen", zerovec::derive(Serialize))]
#[zerovec::format(zerovec::vecs::Index8)]
pub struct DecimalSymbolStrsBuilder<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub minus_sign_prefix: VarZeroCow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub minus_sign_suffix: VarZeroCow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub plus_sign_prefix: VarZeroCow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub plus_sign_suffix: VarZeroCow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub decimal_separator: VarZeroCow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub grouping_separator: VarZeroCow<'data, str>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub numsys: VarZeroCow<'data, str>,
}
#[cfg(feature = "alloc")]
impl DecimalSymbolStrsBuilder<'_> {
pub fn build(&self) -> VarZeroCow<'static, DecimalSymbolsStrs> {
VarZeroCow::from_encodeable(self)
}
}
#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_decimal::provider))]
pub struct DecimalSymbols<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub strings: VarZeroCow<'data, DecimalSymbolsStrs>,
pub grouping_sizes: GroupingSizes,
}
icu_provider::data_struct!(
DecimalSymbols<'_>,
#[cfg(feature = "datagen")]
);
impl<'a> core::ops::Deref for DecimalSymbols<'a> {
type Target = VarZeroCow<'a, DecimalSymbolsStrs>;
fn deref(&self) -> &Self::Target {
&self.strings
}
}
impl DecimalSymbols<'static> {
#[cfg(feature = "datagen")]
pub fn new_en_for_testing() -> Self {
let strings = DecimalSymbolStrsBuilder {
minus_sign_prefix: VarZeroCow::new_borrowed("-"),
minus_sign_suffix: VarZeroCow::new_borrowed(""),
plus_sign_prefix: VarZeroCow::new_borrowed("+"),
plus_sign_suffix: VarZeroCow::new_borrowed(""),
decimal_separator: VarZeroCow::new_borrowed("."),
grouping_separator: VarZeroCow::new_borrowed(","),
numsys: VarZeroCow::new_borrowed("latn"),
};
Self {
strings: VarZeroCow::from_encodeable(&strings),
grouping_sizes: GroupingSizes {
primary: 3,
secondary: 3,
min_grouping: 1,
},
}
}
}
#[cfg(feature = "unstable")]
icu_provider::data_marker!(
DecimalCompactLongV1,
CompactPatterns<'static, SinglePlaceholder>,
);
#[cfg(feature = "unstable")]
icu_provider::data_marker!(
DecimalCompactShortV1,
CompactPatterns<'static, SinglePlaceholder>,
);
#[derive(Debug, Clone, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_decimal::provider))]
#[cfg(feature = "unstable")]
pub struct CompactPatterns<'a, P: PatternBackend>(
pub VarZeroVec<'a, VarTupleULE<u8, PluralElementsPackedULE<Pattern<P>>>>,
);
#[cfg(feature = "datagen")]
#[cfg(feature = "unstable")]
impl<'data, P: PatternBackend> serde::Serialize for CompactPatterns<'data, P>
where
Pattern<P>: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
#[cfg(feature = "serde")]
#[cfg(feature = "unstable")]
impl<'de, 'data, P: PatternBackend> serde::Deserialize<'de> for CompactPatterns<'data, P>
where
'de: 'data,
Box<Pattern<P>>: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
VarZeroVec::<VarTupleULE<u8, PluralElementsPackedULE<Pattern<P>>>>::deserialize(
deserializer,
)
.map(Self)
}
}
#[cfg(feature = "unstable")]
impl<P: PatternBackend> icu_provider::ule::MaybeAsVarULE for CompactPatterns<'_, P> {
type EncodedStruct = [()];
}
#[cfg(feature = "datagen")]
#[cfg(feature = "unstable")]
impl<P: PatternBackend> icu_provider::ule::MaybeEncodeAsVarULE for CompactPatterns<'_, P> {
type EncodeableStruct<'b>
= &'b [()]
where
Self: 'b;
fn maybe_as_encodeable<'b>(&'b self) -> Option<Self::EncodeableStruct<'b>> {
None
}
}
#[cfg(feature = "datagen")]
#[cfg(feature = "unstable")]
impl<P: PatternBackend> CompactPatterns<'static, P> {
#[allow(clippy::type_complexity)]
pub fn new(
patterns: alloc::collections::BTreeMap<
u8,
(u8, icu_plurals::PluralElements<Box<Pattern<P>>>),
>,
zero_magnitude: Option<&icu_plurals::PluralElements<&Pattern<P>>>,
) -> Result<Self, DataError> {
use icu_plurals::provider::FourBitMetadata;
use icu_plurals::PluralElements;
use zerovec::ule::encode_varule_to_box;
use zerovec::ule::vartuple::VarTuple;
use zerovec::vecs::VarZeroVecOwned;
if !patterns
.values()
.zip(patterns.values().skip(1))
.all(|(low, high)| low.0 <= high.0)
{
Err(
DataError::custom("Compact exponents should be nondecreasing").with_debug_context(
&patterns
.values()
.map(|(exponent, _)| exponent)
.collect::<Vec<_>>(),
),
)?;
}
let mut deduplicated_patterns: Vec<(
u8,
PluralElements<(FourBitMetadata, Box<Pattern<P>>)>,
)> = Vec::new();
for (log10_type, (exponent, map)) in patterns
.into_iter()
.skip_while(|(_, (_, pattern))| Some(&pattern.as_ref().map(|p| &**p)) == zero_magnitude)
{
if let Some(prev) = deduplicated_patterns.last() {
if prev
.1
.as_ref()
.with_explicit_one_value(None)
.map(|(_, p)| p)
== map.as_ref()
{
continue;
}
}
let Some(metadata) = FourBitMetadata::try_from_byte(log10_type - exponent) else {
return Err(DataError::custom("Pattern has too many zeros")
.with_debug_context(&(log10_type - exponent)));
};
deduplicated_patterns.push((log10_type, map.map(|p| (metadata, p))))
}
#[allow(clippy::unwrap_used)] Ok(Self(
VarZeroVecOwned::try_from_elements(
&deduplicated_patterns
.into_iter()
.map(|(log10_type, plural_map)| {
encode_varule_to_box(&VarTuple {
sized: log10_type,
variable: plural_map,
})
})
.collect::<Vec<Box<VarTupleULE<u8, PluralElementsPackedULE<Pattern<P>>>>>>(),
)
.unwrap()
.into(),
))
}
}
pub(crate) fn load_with_fallback<'a, M: DataMarker>(
provider: &(impl DataProvider<M> + ?Sized),
ids: impl Iterator<Item = DataIdentifierBorrowed<'a>>,
) -> Result<DataResponse<M>, DataError> {
let mut ids = ids.peekable();
while let Some(id) = ids.next() {
if ids.peek().is_some() {
if let Some(r) = provider
.load(DataRequest {
id,
metadata: {
let mut m = DataRequestMetadata::default();
m.silent = true;
m
},
})
.allow_identifier_not_found()?
{
return Ok(r);
}
} else {
return provider.load(DataRequest {
id,
metadata: DataRequestMetadata::default(),
});
}
}
Err(DataErrorKind::InvalidRequest.into_error())
}
impl crate::DecimalFormatterPreferences {
pub(crate) fn nu_id<'a>(
&'a self,
locale: &'a DataLocale,
) -> Option<DataIdentifierBorrowed<'a>> {
self.numbering_system
.as_ref()
.map(|s| s.as_str())
.map(|nu| {
DataIdentifierBorrowed::for_marker_attributes_and_locale(
DataMarkerAttributes::from_str_or_panic(nu),
locale,
)
})
}
}