icu_locale_core/preferences/
locale.rs1#[cfg(feature = "alloc")]
6use crate::subtags::Variants;
7use crate::subtags::{Language, Region, Script, Subtag, Variant};
8use crate::DataLocale;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct LocalePreferences {
13 pub(crate) language: Language,
15 pub(crate) script: Option<Script>,
17 pub(crate) region: Option<Region>,
19 pub(crate) variant: Option<Variant>,
21 pub(crate) subdivision: Option<Subtag>,
23 pub(crate) ue_region: Option<Region>,
25}
26
27impl LocalePreferences {
28 fn to_data_locale_maybe_region_priority(self, region_priority: bool) -> DataLocale {
29 DataLocale {
30 language: self.language,
31 script: self.script,
32 region: match (self.region, self.ue_region) {
33 (Some(_), Some(r)) if region_priority => Some(r),
34 (r, _) => r,
35 },
36 variant: self.variant,
37 subdivision: self.subdivision,
38 }
39 }
40
41 pub fn to_data_locale_region_priority(self) -> DataLocale {
45 self.to_data_locale_maybe_region_priority(true)
46 }
47
48 pub fn to_data_locale_language_priority(self) -> DataLocale {
52 self.to_data_locale_maybe_region_priority(false)
53 }
54}
55impl Default for LocalePreferences {
56 fn default() -> Self {
57 Self::default()
58 }
59}
60
61impl From<&crate::Locale> for LocalePreferences {
62 fn from(loc: &crate::Locale) -> Self {
63 let sd = loc
64 .extensions
65 .unicode
66 .keywords
67 .get(&crate::extensions::unicode::key!("sd"))
68 .and_then(|v| v.as_single_subtag().copied());
69 let ue_region = loc
70 .extensions
71 .unicode
72 .keywords
73 .get(&crate::extensions::unicode::key!("rg"))
74 .and_then(|v| {
75 v.as_single_subtag()
76 .and_then(|s| Region::try_from_str(s.as_str()).ok())
77 });
78 Self {
79 language: loc.id.language,
80 script: loc.id.script,
81 region: loc.id.region,
82 variant: loc.id.variants.iter().copied().next(),
83 subdivision: sd,
84 ue_region,
85 }
86 }
87}
88
89impl From<&crate::LanguageIdentifier> for LocalePreferences {
90 fn from(lid: &crate::LanguageIdentifier) -> Self {
91 Self {
92 language: lid.language,
93 script: lid.script,
94 region: lid.region,
95 variant: lid.variants.iter().copied().next(),
96 subdivision: None,
97 ue_region: None,
98 }
99 }
100}
101
102#[cfg(feature = "alloc")]
103impl From<LocalePreferences> for crate::Locale {
104 fn from(prefs: LocalePreferences) -> Self {
105 Self {
106 id: crate::LanguageIdentifier {
107 language: prefs.language,
108 script: prefs.script,
109 region: prefs.region,
110 variants: prefs
111 .variant
112 .map(Variants::from_variant)
113 .unwrap_or_default(),
114 },
115 extensions: {
116 let mut extensions = crate::extensions::Extensions::default();
117 if let Some(sd) = prefs.subdivision {
118 extensions.unicode.keywords.set(
119 crate::extensions::unicode::key!("sd"),
120 crate::extensions::unicode::Value::from_subtag(Some(sd)),
121 );
122 }
123 if let Some(rg) = prefs.ue_region {
124 #[allow(clippy::unwrap_used)] extensions.unicode.keywords.set(
126 crate::extensions::unicode::key!("rg"),
127 crate::extensions::unicode::Value::try_from_str(rg.as_str()).unwrap(),
128 );
129 }
130 extensions
131 },
132 }
133 }
134}
135
136impl LocalePreferences {
137 pub const fn default() -> Self {
139 Self {
140 language: Language::UNKNOWN,
141 script: None,
142 region: None,
143 variant: None,
144 subdivision: None,
145 ue_region: None,
146 }
147 }
148
149 pub const fn language(&self) -> Language {
151 self.language
152 }
153
154 pub const fn region(&self) -> Option<Region> {
156 self.region
157 }
158
159 pub fn extend(&mut self, other: LocalePreferences) {
161 if !other.language.is_unknown() {
162 self.language = other.language;
163 }
164 if let Some(script) = other.script {
165 self.script = Some(script);
166 }
167 if let Some(region) = other.region {
168 self.region = Some(region);
169 }
170 if let Some(variant) = other.variant {
171 self.variant = Some(variant);
172 }
173 if let Some(sd) = other.subdivision {
174 self.subdivision = Some(sd);
175 }
176 if let Some(ue_region) = other.ue_region {
177 self.ue_region = Some(ue_region);
178 }
179 }
180}