1#[diplomat::bridge]
6pub mod ffi {
7 use crate::errors::ffi::ICU4XError;
8 use alloc::boxed::Box;
9 use core::str;
10 use icu_locid::extensions::unicode::Key;
11 use icu_locid::subtags::{Language, Region, Script};
12 use icu_locid::Locale;
13 use writeable::Writeable;
14
15 use crate::common::ffi::ICU4XOrdering;
16
17 #[diplomat::opaque]
18 #[diplomat::rust_link(icu::locid::Locale, Struct)]
20 pub struct ICU4XLocale(pub Locale);
21
22 impl ICU4XLocale {
23 #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)]
29 #[diplomat::rust_link(icu::locid::Locale::from_str, FnInStruct, hidden)]
30 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "from_string")]
31 pub fn create_from_string(name: &DiplomatStr) -> Result<Box<ICU4XLocale>, ICU4XError> {
32 Ok(Box::new(ICU4XLocale(Locale::try_from_bytes(name)?)))
33 }
34
35 #[diplomat::rust_link(icu::locid::Locale::UND, AssociatedConstantInStruct)]
37 #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "und")]
38 pub fn create_und() -> Box<ICU4XLocale> {
39 Box::new(ICU4XLocale(Locale::UND))
40 }
41
42 #[diplomat::rust_link(icu::locid::Locale, Struct)]
44 pub fn clone(&self) -> Box<ICU4XLocale> {
45 Box::new(ICU4XLocale(self.0.clone()))
46 }
47
48 #[diplomat::rust_link(icu::locid::Locale::id, StructField)]
51 #[diplomat::attr(supports = accessors, getter)]
52 pub fn basename(
53 &self,
54 write: &mut diplomat_runtime::DiplomatWriteable,
55 ) -> Result<(), ICU4XError> {
56 self.0.id.write_to(write)?;
57 Ok(())
58 }
59
60 #[diplomat::rust_link(icu::locid::Locale::extensions, StructField)]
62 pub fn get_unicode_extension(
63 &self,
64 bytes: &DiplomatStr,
65 write: &mut diplomat_runtime::DiplomatWriteable,
66 ) -> Result<(), ICU4XError> {
67 self.0
68 .extensions
69 .unicode
70 .keywords
71 .get(&Key::try_from_bytes(bytes)?)
72 .ok_or(ICU4XError::LocaleUndefinedSubtagError)?
73 .write_to(write)?;
74 Ok(())
75 }
76
77 #[diplomat::rust_link(icu::locid::Locale::id, StructField)]
79 #[diplomat::attr(supports = accessors, getter)]
80 pub fn language(
81 &self,
82 write: &mut diplomat_runtime::DiplomatWriteable,
83 ) -> Result<(), ICU4XError> {
84 self.0.id.language.write_to(write)?;
85 Ok(())
86 }
87
88 #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)]
90 #[diplomat::attr(supports = accessors, setter = "language")]
91 pub fn set_language(&mut self, bytes: &DiplomatStr) -> Result<(), ICU4XError> {
92 self.0.id.language = if bytes.is_empty() {
93 Language::UND
94 } else {
95 Language::try_from_bytes(bytes)?
96 };
97 Ok(())
98 }
99
100 #[diplomat::rust_link(icu::locid::Locale::id, StructField)]
102 #[diplomat::attr(supports = accessors, getter)]
103 pub fn region(
104 &self,
105 write: &mut diplomat_runtime::DiplomatWriteable,
106 ) -> Result<(), ICU4XError> {
107 if let Some(region) = self.0.id.region {
108 region.write_to(write)?;
109 Ok(())
110 } else {
111 Err(ICU4XError::LocaleUndefinedSubtagError)
112 }
113 }
114
115 #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)]
117 #[diplomat::attr(supports = accessors, setter = "region")]
118 pub fn set_region(&mut self, bytes: &DiplomatStr) -> Result<(), ICU4XError> {
119 self.0.id.region = if bytes.is_empty() {
120 None
121 } else {
122 Some(Region::try_from_bytes(bytes)?)
123 };
124 Ok(())
125 }
126
127 #[diplomat::rust_link(icu::locid::Locale::id, StructField)]
129 #[diplomat::attr(supports = accessors, getter)]
130 pub fn script(
131 &self,
132 write: &mut diplomat_runtime::DiplomatWriteable,
133 ) -> Result<(), ICU4XError> {
134 if let Some(script) = self.0.id.script {
135 script.write_to(write)?;
136 Ok(())
137 } else {
138 Err(ICU4XError::LocaleUndefinedSubtagError)
139 }
140 }
141
142 #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)]
144 #[diplomat::attr(supports = accessors, setter = "script")]
145 pub fn set_script(&mut self, bytes: &DiplomatStr) -> Result<(), ICU4XError> {
146 self.0.id.script = if bytes.is_empty() {
147 None
148 } else {
149 Some(Script::try_from_bytes(bytes)?)
150 };
151 Ok(())
152 }
153
154 #[diplomat::rust_link(icu::locid::Locale::canonicalize, FnInStruct)]
158 pub fn canonicalize(
159 bytes: &DiplomatStr,
160 write: &mut DiplomatWriteable,
161 ) -> Result<(), ICU4XError> {
162 Locale::canonicalize(bytes)?.write_to(write)?;
163 Ok(())
164 }
165 #[diplomat::rust_link(icu::locid::Locale::write_to, FnInStruct)]
167 #[diplomat::attr(supports = stringifiers, stringifier)]
168 pub fn to_string(
169 &self,
170 write: &mut diplomat_runtime::DiplomatWriteable,
171 ) -> Result<(), ICU4XError> {
172 self.0.write_to(write)?;
173 Ok(())
174 }
175
176 #[diplomat::rust_link(icu::locid::Locale::normalizing_eq, FnInStruct)]
177 pub fn normalizing_eq(&self, other: &DiplomatStr) -> bool {
178 if let Ok(other) = str::from_utf8(other) {
179 self.0.normalizing_eq(other)
180 } else {
181 false
183 }
184 }
185
186 #[diplomat::rust_link(icu::locid::Locale::strict_cmp, FnInStruct)]
187 #[diplomat::attr(*, disable)]
188 pub fn strict_cmp(&self, other: &DiplomatStr) -> ICU4XOrdering {
189 self.0.strict_cmp(other).into()
190 }
191
192 #[diplomat::rust_link(icu::locid::Locale::strict_cmp, FnInStruct)]
193 #[diplomat::skip_if_ast]
194 #[diplomat::attr(dart, rename = "compareToString")]
195 pub fn strict_cmp_(&self, other: &DiplomatStr) -> core::cmp::Ordering {
196 self.0.strict_cmp(other)
197 }
198
199 #[diplomat::rust_link(icu::locid::Locale::total_cmp, FnInStruct)]
200 #[diplomat::attr(*, disable)]
201 pub fn total_cmp(&self, other: &Self) -> ICU4XOrdering {
202 self.0.total_cmp(&other.0).into()
203 }
204
205 #[diplomat::rust_link(icu::locid::Locale::total_cmp, FnInStruct)]
206 #[diplomat::skip_if_ast]
207 #[diplomat::attr(supports = comparators, comparison)]
208 pub fn total_cmp_(&self, other: &Self) -> core::cmp::Ordering {
209 self.0.total_cmp(&other.0)
210 }
211
212 #[cfg(feature = "provider_test")]
216 #[diplomat::attr(supports = constructors, disable)]
217 pub fn create_en() -> Box<ICU4XLocale> {
218 Box::new(ICU4XLocale(icu_locid::locale!("en")))
219 }
220
221 #[cfg(feature = "provider_test")]
225 #[diplomat::attr(supports = constructors, disable)]
226 pub fn create_bn() -> Box<ICU4XLocale> {
227 Box::new(ICU4XLocale(icu_locid::locale!("bn")))
228 }
229 }
230}
231
232impl ffi::ICU4XLocale {
233 pub fn to_datalocale(&self) -> icu_provider::DataLocale {
234 (&self.0).into()
235 }
236}