• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #[diplomat::abi_rename = "icu4x_{0}_mv1"]
7 #[diplomat::attr(auto, namespace = "icu4x")]
8 pub mod ffi {
9     use alloc::boxed::Box;
10 
11     use crate::errors::ffi::LocaleParseError;
12 
13     use writeable::Writeable;
14 
15     #[diplomat::opaque]
16     /// An ICU4X Locale, capable of representing strings like `"en-US"`.
17     #[diplomat::rust_link(icu::locale::Locale, Struct)]
18     #[diplomat::rust_link(icu::locale::DataLocale, Struct, hidden)]
19     #[diplomat::rust_link(icu::locale::DataLocale::into_locale, FnInStruct, hidden)]
20     pub struct Locale(pub icu_locale_core::Locale);
21 
22     impl Locale {
23         /// Construct an [`Locale`] 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::locale::Locale::try_from_str, FnInStruct)]
29         #[diplomat::rust_link(icu::locale::Locale::try_from_utf8, FnInStruct, hidden)]
30         #[diplomat::rust_link(icu::locale::Locale::from_str, FnInStruct, hidden)]
31         #[diplomat::rust_link(icu::locale::DataLocale::from_str, FnInStruct, hidden)]
32         #[diplomat::rust_link(icu::locale::DataLocale::try_from_str, FnInStruct, hidden)]
33         #[diplomat::rust_link(icu::locale::DataLocale::try_from_utf8, FnInStruct, hidden)]
34         #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
35         #[diplomat::demo(default_constructor)]
from_string(name: &DiplomatStr) -> Result<Box<Locale>, LocaleParseError>36         pub fn from_string(name: &DiplomatStr) -> Result<Box<Locale>, LocaleParseError> {
37             Ok(Box::new(Locale(icu_locale_core::Locale::try_from_utf8(
38                 name,
39             )?)))
40         }
41 
42         /// Construct a default undefined [`Locale`] "und".
43         #[diplomat::rust_link(icu::locale::Locale::default, FnInStruct)]
44         #[diplomat::rust_link(icu::locale::DataLocale::default, FnInStruct, hidden)]
45         #[diplomat::rust_link(icu::locale::DataLocale::is_default, FnInStruct, hidden)]
46         #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
und() -> Box<Locale>47         pub fn und() -> Box<Locale> {
48             Box::new(Locale(icu_locale_core::Locale::default()))
49         }
50 
51         /// Clones the [`Locale`].
52         #[diplomat::rust_link(icu::locale::Locale, Struct)]
clone(&self) -> Box<Locale>53         pub fn clone(&self) -> Box<Locale> {
54             Box::new(Locale(self.0.clone()))
55         }
56 
57         /// Returns a string representation of the `LanguageIdentifier` part of
58         /// [`Locale`].
59         #[diplomat::rust_link(icu::locale::Locale::id, StructField)]
60         #[diplomat::attr(auto, getter)]
basename(&self, write: &mut diplomat_runtime::DiplomatWrite)61         pub fn basename(&self, write: &mut diplomat_runtime::DiplomatWrite) {
62             let _infallible = self.0.id.write_to(write);
63         }
64 
65         /// Returns a string representation of the unicode extension.
66         #[diplomat::rust_link(icu::locale::Locale::extensions, StructField)]
get_unicode_extension( &self, s: &DiplomatStr, write: &mut diplomat_runtime::DiplomatWrite, ) -> Option<()>67         pub fn get_unicode_extension(
68             &self,
69             s: &DiplomatStr,
70             write: &mut diplomat_runtime::DiplomatWrite,
71         ) -> Option<()> {
72             icu_locale_core::extensions::unicode::Key::try_from_utf8(s)
73                 .ok()
74                 .and_then(|k| self.0.extensions.unicode.keywords.get(&k))
75                 .map(|v| {
76                     let _infallible = v.write_to(write);
77                 })
78         }
79 
80         /// Returns a string representation of [`Locale`] language.
81         #[diplomat::rust_link(icu::locale::Locale::id, StructField)]
82         #[diplomat::attr(auto, getter)]
language(&self, write: &mut diplomat_runtime::DiplomatWrite)83         pub fn language(&self, write: &mut diplomat_runtime::DiplomatWrite) {
84             let _infallible = self.0.id.language.write_to(write);
85         }
86 
87         /// Set the language part of the [`Locale`].
88         #[diplomat::rust_link(icu::locale::Locale::try_from_str, FnInStruct)]
89         #[diplomat::rust_link(icu::locale::Locale::try_from_utf8, FnInStruct, hidden)]
90         #[diplomat::attr(auto, setter = "language")]
set_language(&mut self, s: &DiplomatStr) -> Result<(), LocaleParseError>91         pub fn set_language(&mut self, s: &DiplomatStr) -> Result<(), LocaleParseError> {
92             self.0.id.language = if s.is_empty() {
93                 icu_locale_core::subtags::Language::UND
94             } else {
95                 icu_locale_core::subtags::Language::try_from_utf8(s)?
96             };
97             Ok(())
98         }
99 
100         /// Returns a string representation of [`Locale`] region.
101         #[diplomat::rust_link(icu::locale::Locale::id, StructField)]
102         #[diplomat::attr(auto, getter)]
region(&self, write: &mut diplomat_runtime::DiplomatWrite) -> Option<()>103         pub fn region(&self, write: &mut diplomat_runtime::DiplomatWrite) -> Option<()> {
104             self.0.id.region.map(|region| {
105                 let _infallible = region.write_to(write);
106             })
107         }
108 
109         /// Set the region part of the [`Locale`].
110         #[diplomat::rust_link(icu::locale::Locale::try_from_str, FnInStruct)]
111         #[diplomat::rust_link(icu::locale::Locale::try_from_utf8, FnInStruct, hidden)]
112         #[diplomat::attr(all(supports = accessors, not(dart)), setter = "region")]
set_region(&mut self, s: &DiplomatStr) -> Result<(), LocaleParseError>113         pub fn set_region(&mut self, s: &DiplomatStr) -> Result<(), LocaleParseError> {
114             self.0.id.region = if s.is_empty() {
115                 None
116             } else {
117                 Some(icu_locale_core::subtags::Region::try_from_utf8(s)?)
118             };
119             Ok(())
120         }
121 
122         /// Returns a string representation of [`Locale`] script.
123         #[diplomat::rust_link(icu::locale::Locale::id, StructField)]
124         #[diplomat::attr(auto, getter)]
script(&self, write: &mut diplomat_runtime::DiplomatWrite) -> Option<()>125         pub fn script(&self, write: &mut diplomat_runtime::DiplomatWrite) -> Option<()> {
126             self.0.id.script.map(|script| {
127                 let _infallible = script.write_to(write);
128             })
129         }
130 
131         /// Set the script part of the [`Locale`]. Pass an empty string to remove the script.
132         #[diplomat::rust_link(icu::locale::Locale::try_from_str, FnInStruct)]
133         #[diplomat::rust_link(icu::locale::Locale::try_from_utf8, FnInStruct, hidden)]
134         #[diplomat::attr(all(supports = accessors, not(dart)), setter = "script")]
set_script(&mut self, s: &DiplomatStr) -> Result<(), LocaleParseError>135         pub fn set_script(&mut self, s: &DiplomatStr) -> Result<(), LocaleParseError> {
136             self.0.id.script = if s.is_empty() {
137                 None
138             } else {
139                 Some(icu_locale_core::subtags::Script::try_from_utf8(s)?)
140             };
141             Ok(())
142         }
143 
144         /// Normalizes a locale string.
145         #[diplomat::rust_link(icu::locale::Locale::normalize, FnInStruct)]
146         #[diplomat::rust_link(icu::locale::Locale::normalize_utf8, FnInStruct, hidden)]
normalize( s: &DiplomatStr, write: &mut DiplomatWrite, ) -> Result<(), LocaleParseError>147         pub fn normalize(
148             s: &DiplomatStr,
149             write: &mut DiplomatWrite,
150         ) -> Result<(), LocaleParseError> {
151             let _infallible = icu_locale_core::Locale::normalize_utf8(s)?.write_to(write);
152             Ok(())
153         }
154         /// Returns a string representation of [`Locale`].
155         #[diplomat::rust_link(icu::locale::Locale::write_to, FnInStruct)]
156         #[diplomat::rust_link(icu::locale::Locale::to_string, FnInStruct, hidden)]
157         #[diplomat::rust_link(icu::locale::DataLocale::to_string, FnInStruct, hidden)]
158         #[diplomat::rust_link(icu::locale::DataLocale::write_to, FnInStruct, hidden)]
159         #[diplomat::attr(auto, stringifier)]
to_string(&self, write: &mut diplomat_runtime::DiplomatWrite)160         pub fn to_string(&self, write: &mut diplomat_runtime::DiplomatWrite) {
161             let _infallible = self.0.write_to(write);
162         }
163 
164         #[diplomat::rust_link(icu::locale::Locale::normalizing_eq, FnInStruct)]
normalizing_eq(&self, other: &DiplomatStr) -> bool165         pub fn normalizing_eq(&self, other: &DiplomatStr) -> bool {
166             if let Ok(other) = core::str::from_utf8(other) {
167                 self.0.normalizing_eq(other)
168             } else {
169                 // invalid UTF8 won't be allowed in locales anyway
170                 false
171             }
172         }
173 
174         #[diplomat::rust_link(icu::locale::Locale::strict_cmp, FnInStruct)]
compare_to_string(&self, other: &DiplomatStr) -> core::cmp::Ordering175         pub fn compare_to_string(&self, other: &DiplomatStr) -> core::cmp::Ordering {
176             self.0.strict_cmp(other)
177         }
178 
179         #[diplomat::rust_link(icu::locale::Locale::total_cmp, FnInStruct)]
180         #[diplomat::rust_link(icu::locale::DataLocale::strict_cmp, FnInStruct, hidden)]
181         #[diplomat::rust_link(icu::locale::DataLocale::total_cmp, FnInStruct, hidden)]
182         #[diplomat::attr(auto, comparison)]
compare_to(&self, other: &Self) -> core::cmp::Ordering183         pub fn compare_to(&self, other: &Self) -> core::cmp::Ordering {
184             self.0.total_cmp(&other.0)
185         }
186     }
187 }
188 
189 impl ffi::Locale {
to_datalocale(&self) -> icu_provider::DataLocale190     pub fn to_datalocale(&self) -> icu_provider::DataLocale {
191         (&self.0).into()
192     }
193 }
194