use alloc::borrow::Cow;
use icu_provider::prelude::*;
use tinystr::UnvalidatedTinyAsciiStr;
use zerovec::{VarZeroVec, ZeroMap};
#[cfg(feature = "serde")]
use icu_pattern::DoublePlaceholder;
use icu_pattern::DoublePlaceholderPattern;
use crate::dimension::currency::options::Width;
use crate::dimension::currency::CurrencyCode;
#[cfg(feature = "compiled_data")]
pub use crate::provider::Baked;
icu_provider::data_marker!(
CurrencyEssentialsV1,
CurrencyEssentials<'static>
);
#[derive(Clone, PartialEq, Debug, 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_experimental::dimension::provider::currency::essentials))]
#[yoke(prove_covariance_manually)]
pub struct CurrencyEssentials<'data> {
#[cfg_attr(feature = "serde", serde(borrow))]
pub pattern_config_map: ZeroMap<'data, UnvalidatedTinyAsciiStr<3>, CurrencyPatternConfig>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<DoublePlaceholder, _>"
)
)]
pub standard_pattern: Cow<'data, DoublePlaceholderPattern>,
#[cfg_attr(
feature = "serde",
serde(
borrow,
deserialize_with = "icu_pattern::deserialize_borrowed_cow::<DoublePlaceholder, _>"
)
)]
pub standard_alpha_next_to_number_pattern: Cow<'data, DoublePlaceholderPattern>,
#[cfg_attr(feature = "serde", serde(borrow))]
pub placeholders: VarZeroVec<'data, str>,
pub default_pattern_config: CurrencyPatternConfig,
}
icu_provider::data_struct!(CurrencyEssentials<'_>, #[cfg(feature = "datagen")]);
#[zerovec::make_ule(PatternSelectionULE)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_experimental::dimension::provider::currency::essentials))]
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum PatternSelection {
#[default]
Standard = 0,
StandardAlphaNextToNumber = 1,
}
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_experimental::dimension::provider::currency::essentials))]
#[derive(Copy, Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
#[repr(u16)]
pub enum PlaceholderValue {
Index(u16),
ISO,
}
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_experimental::dimension::provider::currency::essentials))]
#[derive(Copy, Debug, Clone, Default, PartialEq, PartialOrd, Eq, Ord)]
pub struct CurrencyPatternConfig {
pub short_pattern_selection: PatternSelection,
pub narrow_pattern_selection: PatternSelection,
pub short_placeholder_value: Option<PlaceholderValue>,
pub narrow_placeholder_value: Option<PlaceholderValue>,
}
impl<'a> CurrencyEssentials<'a> {
pub(crate) fn name_and_pattern(
&'a self,
width: Width,
currency: &'a CurrencyCode,
) -> (&'a str, &'a DoublePlaceholderPattern, PatternSelection) {
let config = self
.pattern_config_map
.get_copied(¤cy.0.to_unvalidated())
.unwrap_or(self.default_pattern_config);
let placeholder_index = match width {
Width::Short => config.short_placeholder_value,
Width::Narrow => config.narrow_placeholder_value,
};
let currency = match placeholder_index {
Some(PlaceholderValue::Index(index)) => self.placeholders.get(index.into()),
Some(PlaceholderValue::ISO) | None => None,
}
.unwrap_or(currency.0.as_str());
let pattern_selection = match width {
Width::Short => config.short_pattern_selection,
Width::Narrow => config.narrow_pattern_selection,
};
let pattern = match pattern_selection {
PatternSelection::Standard => &*self.standard_pattern,
PatternSelection::StandardAlphaNextToNumber => {
&*self.standard_alpha_next_to_number_pattern
}
};
(currency, pattern, pattern_selection)
}
}