use super::{
DisplayNamesPreferences, LanguageIdentifierDisplayNameOptions, RegionDisplayName,
ScriptDisplayName, VariantDisplayName, load_one,
};
use crate::provider::names::{
LocaleNamesEssentialsV1, LocaleNamesLanguageLongHeavyV1, LocaleNamesLanguageLongLightV1,
LocaleNamesLanguageMediumHeavyV1, LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1, LocaleNamesLanguageMenuMediumHeavyV1,
LocaleNamesLanguageMenuMediumLightV1, LocaleNamesLanguageShortHeavyV1,
LocaleNamesLanguageShortLightV1, LocaleNamesRegionMediumLightV1, LocaleNamesRegionMediumTinyV1,
LocaleNamesRegionShortLightV1, LocaleNamesRegionShortTinyV1, LocaleNamesScriptMediumHeavyV1,
LocaleNamesScriptMediumLightV1, LocaleNamesScriptMediumTinyV1, LocaleNamesScriptShortHeavyV1,
LocaleNamesVariantMediumHeavyV1, MenuNamePartsULE,
};
use crate::size_test_macro::size_test;
use alloc::vec::Vec;
use icu_locale_core::LanguageIdentifier;
use icu_locale_core::subtags::{Language, Region, Script, Variant};
use icu_pattern::{DoublePlaceholderPattern, PatternItem, TryWrap};
use icu_provider::DataPayloadOr;
use icu_provider::marker::ErasedMarker;
use icu_provider::prelude::*;
use tinystr::{TinyAsciiStr, tinystr};
use writeable::LengthHint;
use writeable::{PartsWrite, TryWriteable, adapters::LossyWrap};
use zerovec::VarZeroCow;
#[derive(displaydoc::Display, Debug, Copy, Clone, PartialEq, Eq, Default)]
#[allow(clippy::exhaustive_structs)]
pub struct LanguageIdentifierNameFallbackError;
#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
#[allow(clippy::exhaustive_enums)] enum MenuNamePartsOrString<'a> {
MenuNameParts(VarZeroCow<'a, MenuNamePartsULE>),
String(VarZeroCow<'a, str>),
}
type MenuNamePartsMarker = ErasedMarker<VarZeroCow<'static, MenuNamePartsULE>>;
type StringMarker = ErasedMarker<VarZeroCow<'static, str>>;
size_test!(
LanguageIdentifierDisplayName,
language_identifier_display_name_owned_size,
192
);
macro_rules! table_row {
(try_new_tiny) => {
"| [`try_new_tiny`](Self::try_new_tiny) | \"English (United States)\" | ❌ | ❌ |"
};
(try_new_light) => {
"| [`try_new_light`](Self::try_new_light) | \"American English\" | \"Chinese\" | ❌ |"
};
(try_new_short_light) => {
"| [`try_new_short_light`](Self::try_new_short_light) | \"US English\" | \"Chinese\" | ❌ |"
};
(try_new_long_light) => {
"| [`try_new_long_light`](Self::try_new_long_light) | \"American English\" | \"Mandarin Chinese\" | ❌ |"
};
(try_new_menu_light) => {
"| [`try_new_menu_light`](Self::try_new_menu_light) | \"English (United States)\" | \"Chinese, Mandarin\" | ❌ |"
};
(try_new_short_menu_light) => {
"| [`try_new_short_menu_light`](Self::try_new_short_menu_light) | \"English (US)\" | \"Chinese, Mandarin\" | ❌ |"
};
(try_new_heavy) => {
"| [`try_new_heavy`](Self::try_new_heavy) | \"American English\" | \"Chinese\" | \"Azerbaijani\" |"
};
(try_new_short_heavy) => {
"| [`try_new_short_heavy`](Self::try_new_short_heavy) | \"US English\" | \"Chinese\" | \"Azeri\" |"
};
(try_new_long_heavy) => {
"| [`try_new_long_heavy`](Self::try_new_long_heavy) | \"American English\" | \"Mandarin Chinese\" | \"Azerbaijani\" |"
};
(try_new_menu_heavy) => {
"| [`try_new_menu_heavy`](Self::try_new_menu_heavy) | \"English (United States)\" | \"Chinese, Mandarin\" | \"Azerbaijani\" |"
};
(try_new_short_menu_heavy) => {
"| [`try_new_short_menu_heavy`](Self::try_new_short_menu_heavy) | \"English (US)\" | \"Chinese, Mandarin\" | \"Azeri\" |"
};
}
#[doc = concat!(table_row!(try_new_tiny), "\n")]
#[doc = concat!(table_row!(try_new_light), "\n")]
#[doc = concat!(table_row!(try_new_short_light), "\n")]
#[doc = concat!(table_row!(try_new_long_light), "\n")]
#[doc = concat!(table_row!(try_new_menu_light), "\n")]
#[doc = concat!(table_row!(try_new_short_menu_light), "\n")]
#[doc = concat!(table_row!(try_new_heavy), "\n")]
#[doc = concat!(table_row!(try_new_short_heavy), "\n")]
#[doc = concat!(table_row!(try_new_long_heavy), "\n")]
#[doc = concat!(table_row!(try_new_menu_heavy), "\n")]
#[doc = concat!(table_row!(try_new_short_menu_heavy), "\n")]
#[doc = language_identifier_display_name_owned_size!()]
#[derive(Debug)]
pub struct LanguageIdentifierDisplayName {
language_payload: DataPayloadOr<ErasedMarker<MenuNamePartsOrString<'static>>, Language>,
qualifiers: QualifiersOwned,
}
type VariantPayloads = DataPayloadOr<
ErasedMarker<VarZeroCow<'static, str>>,
Result<Vec<DataPayloadOr<ErasedMarker<VarZeroCow<'static, str>>, Variant>>, Variant>,
>;
#[derive(Debug)]
struct QualifiersOwned {
script_payload: DataPayloadOr<ErasedMarker<VarZeroCow<'static, str>>, Option<Script>>,
region_payload: DataPayloadOr<ErasedMarker<VarZeroCow<'static, str>>, Option<Region>>,
variant_payloads: VariantPayloads,
essentials_payload: DataPayload<LocaleNamesEssentialsV1>,
}
#[inline]
fn make_attributes_for_subtag(subtag: &Language) -> &DataMarkerAttributes {
DataMarkerAttributes::from_str_or_panic(subtag.as_str())
}
#[inline]
fn make_attributes_for_langid(
language: Language,
script: Option<Script>,
region: Option<Region>,
buffer: &mut TinyAsciiStr<16>,
) -> &DataMarkerAttributes {
const HYPHEN: TinyAsciiStr<1> = tinystr!(1, "-");
let lang_str = language.to_tinystr();
*buffer = match (script, region) {
(Some(script), Some(region)) => {
let script_str = script.to_tinystr();
let region_str = region.to_tinystr();
lang_str
.concat::<1, 16>(HYPHEN)
.concat::<4, 16>(script_str)
.concat::<1, 16>(HYPHEN)
.concat::<3, 16>(region_str)
}
(Some(script), None) => {
let script_str = script.to_tinystr();
lang_str.concat::<1, 16>(HYPHEN).concat::<4, 16>(script_str)
}
(None, Some(region)) => {
let region_str = region.to_tinystr();
lang_str.concat::<1, 16>(HYPHEN).concat::<3, 16>(region_str)
}
(None, None) => lang_str.resize::<16>(),
};
DataMarkerAttributes::from_str_or_panic(buffer)
}
#[inline]
fn make_locale(prefs: DisplayNamesPreferences) -> DataLocale {
LocaleNamesLanguageMediumLightV1::make_locale(prefs.locale_preferences)
}
macro_rules! try_load_dialect_name {
($provider:expr, $locale:expr, $subject:expr, [ $first_marker:ident $(, $rest_marker:ident)* $(,)? ]) => {{
let mut result = None;
for (language, script, region) in [
($subject.language, Some($subject.script), Some($subject.region)),
($subject.language, Some($subject.script), None),
($subject.language, None, Some($subject.region)),
] {
let script_val = match script {
Some(Some(s)) => Some(s),
Some(None) => continue,
None => None,
};
let region_val = match region {
Some(Some(r)) => Some(r),
Some(None) => continue,
None => None,
};
let mut buffer = TinyAsciiStr::EMPTY;
let attrs = make_attributes_for_langid(
language,
script_val,
region_val,
&mut buffer,
);
let loaded = load_one::<$first_marker, StringMarker, _>($provider, $locale, attrs)?
$(
.map_or_else(
|| load_one::<$rest_marker, _, _>($provider, $locale, attrs),
|p| Ok::<_, DataError>(Some(p)),
)?
)*;
if let Some(payload) = loaded {
if script_val.is_some() {
$subject.script = None;
}
if region_val.is_some() {
$subject.region = None;
}
result = Some(payload.map_project(|p, _| MenuNamePartsOrString::String(p)));
break;
}
}
Ok::<_, DataError>(result)
}};
}
impl LanguageIdentifierDisplayName {
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_light,
try_new_light_with_buffer_provider,
try_new_light_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_light)]
pub fn try_new_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[
LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1
]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_light_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_tiny,
try_new_tiny_with_buffer_provider,
try_new_tiny_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_tiny)]
pub fn try_new_tiny_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[LocaleNamesLanguageMediumTinyV1]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload = load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_tiny_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_short_light,
try_new_short_light_with_buffer_provider,
try_new_short_light_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_short_light)]
pub fn try_new_short_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageShortLightV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionShortLightV1>
+ DataProvider<LocaleNamesRegionShortTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[
LocaleNamesLanguageShortLightV1,
LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1
]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageShortLightV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_short_light_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_long_light,
try_new_long_light_with_buffer_provider,
try_new_long_light_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_long_light)]
pub fn try_new_long_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageLongLightV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[
LocaleNamesLanguageLongLightV1,
LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1
]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageLongLightV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_light_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_menu_light,
try_new_menu_light_with_buffer_provider,
try_new_menu_light_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_menu_light)]
pub fn try_new_menu_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
_options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMenuMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let attrs = make_attributes_for_subtag(&subject.language);
let mut language_payload = load_one::<LocaleNamesLanguageMenuMediumLightV1, _, _>(
provider, &locale, attrs,
)?
.map(|payload: DataPayload<MenuNamePartsMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::MenuNameParts(p))
});
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_light_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_short_menu_light,
try_new_short_menu_light_with_buffer_provider,
try_new_short_menu_light_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_short_menu_light)]
pub fn try_new_short_menu_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
_options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMenuMediumLightV1>
+ DataProvider<LocaleNamesLanguageShortLightV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionShortLightV1>
+ DataProvider<LocaleNamesRegionShortTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let attrs = make_attributes_for_subtag(&subject.language);
let mut language_payload = load_one::<LocaleNamesLanguageMenuMediumLightV1, _, _>(
provider, &locale, attrs,
)?
.map(|payload: DataPayload<MenuNamePartsMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::MenuNameParts(p))
});
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageShortLightV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_short_light_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_heavy,
try_new_heavy_with_buffer_provider,
try_new_heavy_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_heavy)]
pub fn try_new_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[
LocaleNamesLanguageMediumHeavyV1,
LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1
]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageMediumHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_heavy_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_short_heavy,
try_new_short_heavy_with_buffer_provider,
try_new_short_heavy_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_short_heavy)]
pub fn try_new_short_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageShortHeavyV1>
+ DataProvider<LocaleNamesLanguageShortLightV1>
+ DataProvider<LocaleNamesLanguageMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptShortHeavyV1>
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionShortLightV1>
+ DataProvider<LocaleNamesRegionShortTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[
LocaleNamesLanguageShortHeavyV1,
LocaleNamesLanguageShortLightV1,
LocaleNamesLanguageMediumHeavyV1,
LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1
]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageShortHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageShortLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumHeavyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_short_heavy_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_long_heavy,
try_new_long_heavy_with_buffer_provider,
try_new_long_heavy_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_long_heavy)]
pub fn try_new_long_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
mut subject: LanguageIdentifier,
options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageLongHeavyV1>
+ DataProvider<LocaleNamesLanguageLongLightV1>
+ DataProvider<LocaleNamesLanguageMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let load_dialect = options.should_load_dialect();
let mut language_payload = None;
if load_dialect {
language_payload = try_load_dialect_name!(
provider,
&locale,
subject,
[
LocaleNamesLanguageLongHeavyV1,
LocaleNamesLanguageLongLightV1,
LocaleNamesLanguageMediumHeavyV1,
LocaleNamesLanguageMediumLightV1,
LocaleNamesLanguageMediumTinyV1
]
)?;
}
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageLongHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageLongLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumHeavyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_heavy_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_menu_heavy,
try_new_menu_heavy_with_buffer_provider,
try_new_menu_heavy_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_menu_heavy)]
pub fn try_new_menu_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
_options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMenuMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMenuMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let attrs = make_attributes_for_subtag(&subject.language);
let mut language_payload =
load_one::<LocaleNamesLanguageMenuMediumHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMenuMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<MenuNamePartsMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::MenuNameParts(p))
});
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageMediumHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_heavy_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
icu_provider::gen_buffer_data_constructors!(
(prefs: DisplayNamesPreferences, subject: LanguageIdentifier, options: LanguageIdentifierDisplayNameOptions) -> result: Result<Self, DataError>,
functions: [
try_new_short_menu_heavy,
try_new_short_menu_heavy_with_buffer_provider,
try_new_short_menu_heavy_unstable,
Self
]
);
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new_short_menu_heavy)]
pub fn try_new_short_menu_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
_options: LanguageIdentifierDisplayNameOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesLanguageMenuMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMenuMediumLightV1>
+ DataProvider<LocaleNamesLanguageShortHeavyV1>
+ DataProvider<LocaleNamesLanguageShortLightV1>
+ DataProvider<LocaleNamesLanguageMediumHeavyV1>
+ DataProvider<LocaleNamesLanguageMediumLightV1>
+ DataProvider<LocaleNamesLanguageMediumTinyV1>
+ DataProvider<LocaleNamesScriptShortHeavyV1>
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionShortLightV1>
+ DataProvider<LocaleNamesRegionShortTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
let locale = make_locale(prefs);
let attrs = make_attributes_for_subtag(&subject.language);
let mut language_payload =
load_one::<LocaleNamesLanguageMenuMediumHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMenuMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<MenuNamePartsMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::MenuNameParts(p))
});
if language_payload.is_none() {
let attrs = make_attributes_for_subtag(&subject.language);
language_payload =
load_one::<LocaleNamesLanguageShortHeavyV1, _, _>(provider, &locale, attrs)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageShortLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumHeavyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumLightV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map_or_else(
|| {
load_one::<LocaleNamesLanguageMediumTinyV1, _, _>(
provider, &locale, attrs,
)
},
|p| Ok(Some(p)),
)?
.map(|payload: DataPayload<StringMarker>| {
payload.map_project(|p, _| MenuNamePartsOrString::String(p))
});
}
let language_payload = match language_payload {
Some(payload) => DataPayloadOr::from_payload(payload),
None => DataPayloadOr::from_other(subject.language),
};
let qualifiers = QualifiersOwned::try_new_short_heavy_unstable(provider, prefs, subject)?;
Ok(Self {
language_payload,
qualifiers,
})
}
}
impl QualifiersOwned {
fn try_new_internal_unstable<D, FS, FR, FV>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
load_script: FS,
load_region: FR,
load_variant: FV,
) -> Result<Self, DataError>
where
D: ?Sized + DataProvider<LocaleNamesEssentialsV1>,
FS: Fn(&D, DisplayNamesPreferences, Script) -> Result<ScriptDisplayName, DataError>,
FR: Fn(&D, DisplayNamesPreferences, Region) -> Result<RegionDisplayName, DataError>,
FV: Fn(&D, DisplayNamesPreferences, Variant) -> Result<VariantDisplayName, DataError>,
{
let script_payload = if let Some(script) = subject.script {
match load_script(provider, prefs, script).allow_identifier_not_found()? {
Some(obj) => obj.payload.cast().map_other(Some),
None => DataPayloadOr::from_other(Some(script)),
}
} else {
DataPayloadOr::from_other(None)
};
let region_payload = if let Some(region) = subject.region {
match load_region(provider, prefs, region).allow_identifier_not_found()? {
Some(obj) => obj.payload.cast().map_other(Some),
None => DataPayloadOr::from_other(Some(region)),
}
} else {
DataPayloadOr::from_other(None)
};
let load_variant_helper = |variant: Variant| -> Result<
DataPayloadOr<ErasedMarker<VarZeroCow<'static, str>>, Variant>,
DataError,
> {
match load_variant(provider, prefs, variant).allow_identifier_not_found()? {
Some(obj) => Ok(obj.payload.cast()),
None => Ok(DataPayloadOr::from_other(variant)),
}
};
let mut variant_results = subject
.variants
.iter()
.map(|variant| load_variant_helper(*variant));
let variant_payloads = if let Some(first) = variant_results.next() {
if let Some(second) = variant_results.next() {
let payload_vec = [first, second]
.into_iter()
.chain(variant_results)
.collect::<Result<Vec<_>, _>>()?;
DataPayloadOr::from_other(Ok(payload_vec))
} else {
match first?.into_inner() {
Ok(payload) => DataPayloadOr::from_payload(payload),
Err(fallback_code) => DataPayloadOr::from_other(Err(fallback_code)),
}
}
} else {
DataPayloadOr::from_other(Ok(Vec::new()))
};
let essentials_payload = provider
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&LocaleNamesEssentialsV1::make_locale(
prefs.locale_preferences,
)),
..Default::default()
})?
.payload;
Ok(Self {
script_payload,
region_payload,
variant_payloads,
essentials_payload,
})
}
fn try_new_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
Self::try_new_internal_unstable(
provider,
prefs,
subject,
ScriptDisplayName::try_new_light_unstable,
RegionDisplayName::try_new_light_unstable,
VariantDisplayName::try_new_heavy_unstable,
)
}
fn try_new_tiny_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
Self::try_new_internal_unstable(
provider,
prefs,
subject,
ScriptDisplayName::try_new_tiny_unstable,
RegionDisplayName::try_new_tiny_unstable,
VariantDisplayName::try_new_heavy_unstable,
)
}
fn try_new_short_light_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionShortLightV1>
+ DataProvider<LocaleNamesRegionShortTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
Self::try_new_internal_unstable(
provider,
prefs,
subject,
ScriptDisplayName::try_new_light_unstable,
RegionDisplayName::try_new_short_light_unstable,
VariantDisplayName::try_new_heavy_unstable,
)
}
fn try_new_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
Self::try_new_internal_unstable(
provider,
prefs,
subject,
ScriptDisplayName::try_new_heavy_unstable,
RegionDisplayName::try_new_light_unstable,
VariantDisplayName::try_new_heavy_unstable,
)
}
fn try_new_short_heavy_unstable<D>(
provider: &D,
prefs: DisplayNamesPreferences,
subject: LanguageIdentifier,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<LocaleNamesScriptShortHeavyV1>
+ DataProvider<LocaleNamesScriptMediumHeavyV1>
+ DataProvider<LocaleNamesScriptMediumLightV1>
+ DataProvider<LocaleNamesScriptMediumTinyV1>
+ DataProvider<LocaleNamesRegionShortLightV1>
+ DataProvider<LocaleNamesRegionShortTinyV1>
+ DataProvider<LocaleNamesRegionMediumLightV1>
+ DataProvider<LocaleNamesRegionMediumTinyV1>
+ DataProvider<LocaleNamesVariantMediumHeavyV1>
+ DataProvider<LocaleNamesEssentialsV1>,
{
Self::try_new_internal_unstable(
provider,
prefs,
subject,
ScriptDisplayName::try_new_short_heavy_unstable,
RegionDisplayName::try_new_short_light_unstable,
VariantDisplayName::try_new_heavy_unstable,
)
}
}
impl LanguageIdentifierDisplayName {
pub fn as_borrowed(&self) -> LanguageIdentifierDisplayNameBorrowed<'_> {
let mut qualifiers = self.qualifiers.as_borrowed();
let base_name = match self.language_payload.get() {
Ok(MenuNamePartsOrString::String(string)) => NameOrFallback(Ok(string.as_ref())),
Ok(MenuNamePartsOrString::MenuNameParts(parts)) => {
if !parts.extension().is_empty() {
qualifiers.menu_extension = Some(parts.extension());
}
NameOrFallback(Ok(parts.core()))
}
Err(lang) => NameOrFallback(Err(lang.as_str())),
};
LanguageIdentifierDisplayNameBorrowed(LossyWrap(LanguageIdentifierDisplayNameInner {
base_name,
qualifiers,
}))
}
}
impl QualifiersOwned {
pub fn as_borrowed(&self) -> QualifiersBorrowed<'_> {
let script = match self.script_payload.get() {
Ok(p) => Some(NameOrFallback(Ok(p.as_ref()))),
Err(Some(script)) => Some(NameOrFallback(Err(script.as_str()))),
Err(None) => None,
};
let region = match self.region_payload.get() {
Ok(p) => Some(NameOrFallback(Ok(p.as_ref()))),
Err(Some(region)) => Some(NameOrFallback(Err(region.as_str()))),
Err(None) => None,
};
let variants = match self.variant_payloads.get() {
Ok(variant_name) => BorrowedVariants::One(NameOrFallback(Ok(variant_name))),
Err(Ok(vec)) => BorrowedVariants::Slice(vec.as_slice()),
Err(Err(variant)) => BorrowedVariants::One(NameOrFallback(Err(variant.as_str()))),
};
QualifiersBorrowed {
menu_extension: None,
script,
region,
variants,
glue: &self.essentials_payload.get().locale_pattern,
separator: &self.essentials_payload.get().locale_separator,
}
}
}
#[derive(Debug, Clone, Copy)]
enum BorrowedVariants<'a> {
One(NameOrFallback<'a>),
Slice(&'a [DataPayloadOr<ErasedMarker<VarZeroCow<'static, str>>, Variant>]),
}
impl BorrowedVariants<'_> {
#[inline]
fn is_empty(&self) -> bool {
matches!(self, Self::Slice([]))
}
}
#[derive(Debug, Clone, Copy)]
pub struct LanguageIdentifierDisplayNameBorrowed<'a>(
pub(crate) LossyWrap<LanguageIdentifierDisplayNameInner<'a>>,
);
#[derive(Debug, Clone, Copy)]
struct NameOrFallback<'a>(Result<&'a str, &'a str>);
writeable::impl_try_writeable_delegate!(
NameOrFallback<'a>,
|&self| &self.0,
Error = LanguageIdentifierNameFallbackError,
|_fallback_str| LanguageIdentifierNameFallbackError,
where 'a
);
#[derive(Debug, Clone, Copy)]
pub(crate) struct LanguageIdentifierDisplayNameInner<'a> {
base_name: NameOrFallback<'a>,
qualifiers: QualifiersBorrowed<'a>,
}
writeable::impl_try_writeable_delegate!(
LanguageIdentifierDisplayNameBorrowed<'_>,
|&self| &self.0.0,
Error = LanguageIdentifierNameFallbackError
);
writeable::impl_writeable_delegate!(LanguageIdentifierDisplayNameBorrowed<'_>, |&self| &self.0);
writeable::impl_display_with_writeable!(LanguageIdentifierDisplayNameBorrowed<'_>);
#[derive(Debug, Copy, Clone)]
struct QualifiersBorrowed<'a> {
menu_extension: Option<&'a str>,
script: Option<NameOrFallback<'a>>,
region: Option<NameOrFallback<'a>>,
variants: BorrowedVariants<'a>,
glue: &'a DoublePlaceholderPattern,
separator: &'a DoublePlaceholderPattern,
}
impl<'a> QualifiersBorrowed<'a> {
fn separator_str(&self) -> &'a str {
let mut separator_str = ", ";
for item in self.separator.iter() {
if let PatternItem::Literal(s) = item {
separator_str = s;
break;
}
}
separator_str
}
fn is_empty(&self) -> bool {
self.menu_extension.is_none()
&& self.script.is_none()
&& self.region.is_none()
&& self.variants.is_empty()
}
}
impl<'a> TryWriteable for QualifiersBorrowed<'a> {
type Error = LanguageIdentifierNameFallbackError;
fn try_write_to_parts<S: PartsWrite + ?Sized>(
&self,
sink: &mut S,
) -> Result<Result<(), Self::Error>, core::fmt::Error> {
let mut first = true;
let separator_str = self.separator_str();
if let Some(menu_extension) = self.menu_extension {
sink.write_str(menu_extension)?;
first = false;
}
let mut write_item = |sink: &mut S,
res: NameOrFallback|
-> Result<
Result<(), LanguageIdentifierNameFallbackError>,
core::fmt::Error,
> {
if !first {
sink.write_str(separator_str)?;
}
first = false;
res.try_write_to_parts(sink)
};
let mut result = Ok(());
if let Some(script) = self.script {
result = result.and(write_item(sink, script)?);
}
if let Some(region) = self.region {
result = result.and(write_item(sink, region)?);
}
match self.variants {
BorrowedVariants::One(variant) => {
result = result.and(write_item(sink, variant)?);
}
BorrowedVariants::Slice(slice) => {
for item in slice.iter() {
let res = match item.get() {
Ok(p) => NameOrFallback(Ok(p.as_ref())),
Err(var) => NameOrFallback(Err(var.as_str())),
};
result = result.and(write_item(sink, res)?);
}
}
}
Ok(result)
}
fn writeable_length_hint(&self) -> LengthHint {
let mut length_hint = LengthHint::exact(0);
let mut num_items = 0;
if let Some(menu_extension) = self.menu_extension {
length_hint += writeable::Writeable::writeable_length_hint(&menu_extension);
num_items += 1;
}
if let Some(script) = self.script {
length_hint += script.writeable_length_hint();
num_items += 1;
}
if let Some(region) = self.region {
length_hint += region.writeable_length_hint();
num_items += 1;
}
match self.variants {
BorrowedVariants::One(variant) => {
length_hint += variant.writeable_length_hint();
num_items += 1;
}
BorrowedVariants::Slice(slice) => {
for item in slice.iter() {
length_hint += match item.get() {
Ok(p) => writeable::Writeable::writeable_length_hint(&**p),
Err(var) => writeable::Writeable::writeable_length_hint(var.as_str()),
};
num_items += 1;
}
}
}
length_hint += LengthHint::exact(self.separator_str().len() * (num_items - 1));
length_hint
}
}
impl<'a> TryWriteable for LanguageIdentifierDisplayNameInner<'a> {
type Error = LanguageIdentifierNameFallbackError;
fn try_write_to_parts<S: PartsWrite + ?Sized>(
&self,
sink: &mut S,
) -> Result<Result<(), Self::Error>, core::fmt::Error> {
if self.qualifiers.is_empty() {
self.base_name.try_write_to_parts(sink)
} else {
let result = self
.qualifiers
.glue
.try_interpolate(TryWrap((self.base_name, self.qualifiers)))
.try_write_to_parts(sink)?;
Ok(result.map_err(either::Either::into_inner))
}
}
fn writeable_length_hint(&self) -> LengthHint {
if self.qualifiers.is_empty() {
self.base_name.writeable_length_hint()
} else {
self.qualifiers
.glue
.try_interpolate(TryWrap((self.base_name, self.qualifiers)))
.writeable_length_hint()
}
}
fn try_writeable_borrow(&self) -> Option<Result<&str, (Self::Error, &str)>> {
if self.qualifiers.is_empty() {
self.base_name.try_writeable_borrow()
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use icu_locale_core::{langid, locale};
#[test]
fn test_language_identifier_display_name_owned_table() {
let prefs_en = DisplayNamesPreferences::from(locale!("en"));
let options = LanguageIdentifierDisplayNameOptions::default();
let inputs = [langid!("en-US"), langid!("zh"), langid!("az")];
macro_rules! check_row {
($constructor:ident) => {
let items = inputs.iter().map(|id| {
LanguageIdentifierDisplayName::$constructor(prefs_en, id.clone(), options).map(
|display_name| {
display_name
.as_borrowed()
.try_write_to_string()
.map(|s| s.into_owned())
.map_err(|e| e.0)
},
)
});
assert_eq!(
super::super::format_table_row(stringify!($constructor), items),
table_row!($constructor)
);
};
}
check_row!(try_new_tiny);
check_row!(try_new_light);
check_row!(try_new_short_light);
check_row!(try_new_long_light);
check_row!(try_new_menu_light);
check_row!(try_new_short_menu_light);
check_row!(try_new_heavy);
check_row!(try_new_short_heavy);
check_row!(try_new_long_heavy);
check_row!(try_new_menu_heavy);
check_row!(try_new_short_menu_heavy);
}
}