/rust/registry/src/index.crates.io-1949cf8c6b5b557f/icu_capi-1.5.1/src/locale.rs
Line | Count | Source |
1 | | // This file is part of ICU4X. For terms of use, please see the file |
2 | | // called LICENSE at the top level of the ICU4X source tree |
3 | | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | | |
5 | | #[diplomat::bridge] |
6 | | pub 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 | | /// An ICU4X Locale, capable of representing strings like `"en-US"`. |
19 | | #[diplomat::rust_link(icu::locid::Locale, Struct)] |
20 | | pub struct ICU4XLocale(pub Locale); |
21 | | |
22 | | impl ICU4XLocale { |
23 | | /// Construct an [`ICU4XLocale`] from an locale identifier. |
24 | | /// |
25 | | /// This will run the complete locale parsing algorithm. If code size and |
26 | | /// performance are critical and the locale is of a known shape (such as |
27 | | /// `aa-BB`) use `create_und`, `set_language`, `set_script`, and `set_region`. |
28 | | #[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 | 0 | pub fn create_from_string(name: &DiplomatStr) -> Result<Box<ICU4XLocale>, ICU4XError> { |
32 | 0 | Ok(Box::new(ICU4XLocale(Locale::try_from_bytes(name)?))) |
33 | 0 | } |
34 | | |
35 | | /// Construct a default undefined [`ICU4XLocale`] "und". |
36 | | #[diplomat::rust_link(icu::locid::Locale::UND, AssociatedConstantInStruct)] |
37 | | #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "und")] |
38 | 0 | pub fn create_und() -> Box<ICU4XLocale> { |
39 | 0 | Box::new(ICU4XLocale(Locale::UND)) |
40 | 0 | } |
41 | | |
42 | | /// Clones the [`ICU4XLocale`]. |
43 | | #[diplomat::rust_link(icu::locid::Locale, Struct)] |
44 | 0 | pub fn clone(&self) -> Box<ICU4XLocale> { |
45 | 0 | Box::new(ICU4XLocale(self.0.clone())) |
46 | 0 | } |
47 | | |
48 | | /// Write a string representation of the `LanguageIdentifier` part of |
49 | | /// [`ICU4XLocale`] to `write`. |
50 | | #[diplomat::rust_link(icu::locid::Locale::id, StructField)] |
51 | | #[diplomat::attr(supports = accessors, getter)] |
52 | 0 | pub fn basename( |
53 | 0 | &self, |
54 | 0 | write: &mut diplomat_runtime::DiplomatWriteable, |
55 | 0 | ) -> Result<(), ICU4XError> { |
56 | 0 | self.0.id.write_to(write)?; |
57 | 0 | Ok(()) |
58 | 0 | } |
59 | | |
60 | | /// Write a string representation of the unicode extension to `write` |
61 | | #[diplomat::rust_link(icu::locid::Locale::extensions, StructField)] |
62 | 0 | pub fn get_unicode_extension( |
63 | 0 | &self, |
64 | 0 | bytes: &DiplomatStr, |
65 | 0 | write: &mut diplomat_runtime::DiplomatWriteable, |
66 | 0 | ) -> Result<(), ICU4XError> { |
67 | 0 | self.0 |
68 | 0 | .extensions |
69 | 0 | .unicode |
70 | 0 | .keywords |
71 | 0 | .get(&Key::try_from_bytes(bytes)?) |
72 | 0 | .ok_or(ICU4XError::LocaleUndefinedSubtagError)? |
73 | 0 | .write_to(write)?; |
74 | 0 | Ok(()) |
75 | 0 | } |
76 | | |
77 | | /// Write a string representation of [`ICU4XLocale`] language to `write` |
78 | | #[diplomat::rust_link(icu::locid::Locale::id, StructField)] |
79 | | #[diplomat::attr(supports = accessors, getter)] |
80 | 0 | pub fn language( |
81 | 0 | &self, |
82 | 0 | write: &mut diplomat_runtime::DiplomatWriteable, |
83 | 0 | ) -> Result<(), ICU4XError> { |
84 | 0 | self.0.id.language.write_to(write)?; |
85 | 0 | Ok(()) |
86 | 0 | } |
87 | | |
88 | | /// Set the language part of the [`ICU4XLocale`]. |
89 | | #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)] |
90 | | #[diplomat::attr(supports = accessors, setter = "language")] |
91 | 0 | pub fn set_language(&mut self, bytes: &DiplomatStr) -> Result<(), ICU4XError> { |
92 | 0 | self.0.id.language = if bytes.is_empty() { |
93 | 0 | Language::UND |
94 | | } else { |
95 | 0 | Language::try_from_bytes(bytes)? |
96 | | }; |
97 | 0 | Ok(()) |
98 | 0 | } |
99 | | |
100 | | /// Write a string representation of [`ICU4XLocale`] region to `write` |
101 | | #[diplomat::rust_link(icu::locid::Locale::id, StructField)] |
102 | | #[diplomat::attr(supports = accessors, getter)] |
103 | 0 | pub fn region( |
104 | 0 | &self, |
105 | 0 | write: &mut diplomat_runtime::DiplomatWriteable, |
106 | 0 | ) -> Result<(), ICU4XError> { |
107 | 0 | if let Some(region) = self.0.id.region { |
108 | 0 | region.write_to(write)?; |
109 | 0 | Ok(()) |
110 | | } else { |
111 | 0 | Err(ICU4XError::LocaleUndefinedSubtagError) |
112 | | } |
113 | 0 | } |
114 | | |
115 | | /// Set the region part of the [`ICU4XLocale`]. |
116 | | #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)] |
117 | | #[diplomat::attr(supports = accessors, setter = "region")] |
118 | 0 | pub fn set_region(&mut self, bytes: &DiplomatStr) -> Result<(), ICU4XError> { |
119 | 0 | self.0.id.region = if bytes.is_empty() { |
120 | 0 | None |
121 | | } else { |
122 | 0 | Some(Region::try_from_bytes(bytes)?) |
123 | | }; |
124 | 0 | Ok(()) |
125 | 0 | } |
126 | | |
127 | | /// Write a string representation of [`ICU4XLocale`] script to `write` |
128 | | #[diplomat::rust_link(icu::locid::Locale::id, StructField)] |
129 | | #[diplomat::attr(supports = accessors, getter)] |
130 | 0 | pub fn script( |
131 | 0 | &self, |
132 | 0 | write: &mut diplomat_runtime::DiplomatWriteable, |
133 | 0 | ) -> Result<(), ICU4XError> { |
134 | 0 | if let Some(script) = self.0.id.script { |
135 | 0 | script.write_to(write)?; |
136 | 0 | Ok(()) |
137 | | } else { |
138 | 0 | Err(ICU4XError::LocaleUndefinedSubtagError) |
139 | | } |
140 | 0 | } |
141 | | |
142 | | /// Set the script part of the [`ICU4XLocale`]. Pass an empty string to remove the script. |
143 | | #[diplomat::rust_link(icu::locid::Locale::try_from_bytes, FnInStruct)] |
144 | | #[diplomat::attr(supports = accessors, setter = "script")] |
145 | 0 | pub fn set_script(&mut self, bytes: &DiplomatStr) -> Result<(), ICU4XError> { |
146 | 0 | self.0.id.script = if bytes.is_empty() { |
147 | 0 | None |
148 | | } else { |
149 | 0 | Some(Script::try_from_bytes(bytes)?) |
150 | | }; |
151 | 0 | Ok(()) |
152 | 0 | } |
153 | | |
154 | | /// Best effort locale canonicalizer that doesn't need any data |
155 | | /// |
156 | | /// Use ICU4XLocaleCanonicalizer for better control and functionality |
157 | | #[diplomat::rust_link(icu::locid::Locale::canonicalize, FnInStruct)] |
158 | 0 | pub fn canonicalize( |
159 | 0 | bytes: &DiplomatStr, |
160 | 0 | write: &mut DiplomatWriteable, |
161 | 0 | ) -> Result<(), ICU4XError> { |
162 | 0 | Locale::canonicalize(bytes)?.write_to(write)?; |
163 | 0 | Ok(()) |
164 | 0 | } |
165 | | /// Write a string representation of [`ICU4XLocale`] to `write` |
166 | | #[diplomat::rust_link(icu::locid::Locale::write_to, FnInStruct)] |
167 | | #[diplomat::attr(supports = stringifiers, stringifier)] |
168 | 0 | pub fn to_string( |
169 | 0 | &self, |
170 | 0 | write: &mut diplomat_runtime::DiplomatWriteable, |
171 | 0 | ) -> Result<(), ICU4XError> { |
172 | 0 | self.0.write_to(write)?; |
173 | 0 | Ok(()) |
174 | 0 | } |
175 | | |
176 | | #[diplomat::rust_link(icu::locid::Locale::normalizing_eq, FnInStruct)] |
177 | 0 | pub fn normalizing_eq(&self, other: &DiplomatStr) -> bool { |
178 | 0 | if let Ok(other) = str::from_utf8(other) { |
179 | 0 | self.0.normalizing_eq(other) |
180 | | } else { |
181 | | // invalid UTF8 won't be allowed in locales anyway |
182 | 0 | false |
183 | | } |
184 | 0 | } |
185 | | |
186 | | #[diplomat::rust_link(icu::locid::Locale::strict_cmp, FnInStruct)] |
187 | | #[diplomat::attr(*, disable)] |
188 | 0 | pub fn strict_cmp(&self, other: &DiplomatStr) -> ICU4XOrdering { |
189 | 0 | self.0.strict_cmp(other).into() |
190 | 0 | } |
191 | | |
192 | | #[diplomat::rust_link(icu::locid::Locale::strict_cmp, FnInStruct)] |
193 | | #[diplomat::skip_if_ast] |
194 | | #[diplomat::attr(dart, rename = "compareToString")] |
195 | 0 | pub fn strict_cmp_(&self, other: &DiplomatStr) -> core::cmp::Ordering { |
196 | 0 | self.0.strict_cmp(other) |
197 | 0 | } |
198 | | |
199 | | #[diplomat::rust_link(icu::locid::Locale::total_cmp, FnInStruct)] |
200 | | #[diplomat::attr(*, disable)] |
201 | 0 | pub fn total_cmp(&self, other: &Self) -> ICU4XOrdering { |
202 | 0 | self.0.total_cmp(&other.0).into() |
203 | 0 | } |
204 | | |
205 | | #[diplomat::rust_link(icu::locid::Locale::total_cmp, FnInStruct)] |
206 | | #[diplomat::skip_if_ast] |
207 | | #[diplomat::attr(supports = comparators, comparison)] |
208 | 0 | pub fn total_cmp_(&self, other: &Self) -> core::cmp::Ordering { |
209 | 0 | self.0.total_cmp(&other.0) |
210 | 0 | } |
211 | | |
212 | | /// Deprecated |
213 | | /// |
214 | | /// Use `create_from_string("en"). |
215 | | #[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 | | /// Deprecated |
222 | | /// |
223 | | /// Use `create_from_string("bn"). |
224 | | #[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 | | |
232 | | impl ffi::ICU4XLocale { |
233 | 0 | pub fn to_datalocale(&self) -> icu_provider::DataLocale { |
234 | 0 | (&self.0).into() |
235 | 0 | } |
236 | | } |