Coverage Report

Created: 2025-10-28 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}