icu_provider_source/list/
mod.rsuse crate::cldr_serde;
use crate::IterableDataProviderCached;
use crate::SourceDataProvider;
use icu::list::provider::*;
use icu::locale::subtags::language;
use icu_provider::prelude::*;
use std::borrow::Cow;
use std::collections::HashSet;
use std::sync::OnceLock;
fn load<M: DataMarker<DataStruct = ListFormatterPatternsV2<'static>>>(
selff: &SourceDataProvider,
req: DataRequest,
) -> Result<DataResponse<M>, DataError> {
let resource: &cldr_serde::list_patterns::Resource = selff
.cldr()?
.misc()
.read_and_parse(req.id.locale, "listPatterns.json")?;
let data = &resource.main.value.list_patterns;
let patterns = if M::INFO == AndListV2Marker::INFO {
match req.id.marker_attributes.as_str() {
ListFormatterPatternsV2::SHORT_STR => &data.standard_short,
ListFormatterPatternsV2::NARROW_STR => &data.standard_narrow,
ListFormatterPatternsV2::WIDE_STR => &data.standard,
_ => return Err(DataErrorKind::IdentifierNotFound.with_req(M::INFO, req)),
}
} else if M::INFO == OrListV2Marker::INFO {
match req.id.marker_attributes.as_str() {
ListFormatterPatternsV2::SHORT_STR => &data.or_short,
ListFormatterPatternsV2::NARROW_STR => &data.or_narrow,
ListFormatterPatternsV2::WIDE_STR => &data.or,
_ => return Err(DataErrorKind::IdentifierNotFound.with_req(M::INFO, req)),
}
} else if M::INFO == UnitListV2Marker::INFO {
match req.id.marker_attributes.as_str() {
ListFormatterPatternsV2::SHORT_STR => &data.unit_short,
ListFormatterPatternsV2::NARROW_STR => &data.unit_narrow,
ListFormatterPatternsV2::WIDE_STR => &data.unit,
_ => return Err(DataErrorKind::IdentifierNotFound.with_req(M::INFO, req)),
}
} else {
return Err(DataError::custom(
"Unknown marker for ListFormatterPatternsV2",
));
};
let mut patterns = ListFormatterPatternsV2::try_new(
&patterns.start,
&patterns.middle,
&patterns.end,
&patterns.pair,
)?;
if req.id.locale.language == language!("es") {
if M::INFO == AndListV2Marker::INFO || M::INFO == UnitListV2Marker::INFO {
static I_SOUND_BECOMES_E: OnceLock<SpecialCasePattern<'static>> = OnceLock::new();
let i_sound_becomes_e = I_SOUND_BECOMES_E.get_or_init(|| {
SpecialCasePattern {
condition: SerdeDFA::new(Cow::Borrowed("^[iI]|(?:[hH][iI](?:[^aeAE]|$))"))
.expect("Valid regex"),
pattern: ListJoinerPattern::try_from_str("{0} e {1}", false, false)
.expect("Valid pattern"),
}
});
let default =
ListJoinerPattern::try_from_str("{0} y {1}", false, false).expect("valid pattern");
if patterns.end.default == default {
patterns.end.special_case = Some(i_sound_becomes_e.clone());
}
if let Some(pair) = patterns.pair.as_mut() {
if pair.default == default {
pair.special_case = Some(i_sound_becomes_e.clone());
}
}
} else if M::INFO == OrListV2Marker::INFO {
static O_SOUND_BECOMES_U: OnceLock<SpecialCasePattern<'static>> = OnceLock::new();
let o_sound_becomes_u = O_SOUND_BECOMES_U.get_or_init(|| {
SpecialCasePattern {
condition: SerdeDFA::new(Cow::Borrowed(
r"^[oO]|[hH][oO]|8|(?:11(?:[\. ]?[0-9]{3})*(?:,[0-9]*)?(?:[^\.,[0-9]]|$))",
))
.expect("Valid regex"),
pattern: ListJoinerPattern::try_from_str("{0} u {1}", false, false)
.expect("valid pattern"),
}
});
let default =
ListJoinerPattern::try_from_str("{0} o {1}", false, false).expect("valid pattern");
if patterns.end.default == default {
patterns.end.special_case = Some(o_sound_becomes_u.clone());
}
if let Some(pair) = patterns.pair.as_mut() {
if pair.default == default {
pair.special_case = Some(o_sound_becomes_u.clone());
}
}
}
}
if req.id.locale.language == language!("he") {
let dashes_in_front_of_non_hebrew = SpecialCasePattern {
condition: SerdeDFA::new(Cow::Owned(format!(
"^[^{}]",
icu::properties::CodePointMapData::<icu::properties::props::Script>::try_new_unstable(selff)
.map_err(|e| DataError::custom("data for CodePointTrie of Script")
.with_display_context(&e))?
.as_borrowed()
.get_set_for_value(icu::properties::props::Script::Hebrew)
.as_borrowed()
.iter_ranges()
.map(|range| format!(r#"\u{:04x}-\u{:04x}"#, range.start(), range.end()))
.fold(String::new(), |a, b| a + &b)
)))
.expect("valid regex"),
pattern: ListJoinerPattern::try_from_str("{0} \u{05D5}‑{1}", false, false).unwrap(), };
let default = ListJoinerPattern::try_from_str("{0} \u{05D5}{1}", false, false)
.expect("valid pattern"); if patterns.end.default == default {
patterns.end.special_case = Some(dashes_in_front_of_non_hebrew.clone());
}
if let Some(pair) = patterns.pair.as_mut() {
if pair.default == default {
pair.special_case = Some(dashes_in_front_of_non_hebrew.clone());
}
}
}
let metadata = DataResponseMetadata::default();
Ok(DataResponse {
metadata,
payload: DataPayload::from_owned(patterns),
})
}
macro_rules! implement {
($marker:ident) => {
impl DataProvider<$marker> for SourceDataProvider {
fn load(&self, req: DataRequest) -> Result<DataResponse<$marker>, DataError> {
self.check_req::<$marker>(req)?;
load(self, req)
}
}
impl IterableDataProviderCached<$marker> for SourceDataProvider {
fn iter_ids_cached(&self) -> Result<HashSet<DataIdentifierCow<'static>>, DataError> {
Ok(self
.cldr()?
.misc()
.list_locales()?
.flat_map(|l| {
[
ListFormatterPatternsV2::SHORT,
ListFormatterPatternsV2::NARROW,
ListFormatterPatternsV2::WIDE,
]
.into_iter()
.map(move |a| DataIdentifierCow::from_borrowed_and_owned(a, l.clone()))
})
.collect())
}
}
};
}
implement!(AndListV2Marker);
implement!(OrListV2Marker);
implement!(UnitListV2Marker);