icu_capi/
properties_maps.rs

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]
6pub mod ffi {
7    use crate::provider::ffi::ICU4XDataProvider;
8    use alloc::boxed::Box;
9    use icu_collections::codepointtrie::TrieValue;
10    use icu_properties::{maps, GeneralCategory, GeneralCategoryGroup};
11
12    use crate::errors::ffi::ICU4XError;
13    use crate::properties_iter::ffi::CodePointRangeIterator;
14    use crate::properties_sets::ffi::ICU4XCodePointSetData;
15
16    #[diplomat::opaque]
17    /// An ICU4X Unicode Map Property object, capable of querying whether a code point (key) to obtain the Unicode property value, for a specific Unicode property.
18    ///
19    /// For properties whose values fit into 8 bits.
20    #[diplomat::rust_link(icu::properties, Mod)]
21    #[diplomat::rust_link(icu::properties::maps::CodePointMapData, Struct)]
22    #[diplomat::rust_link(icu::properties::maps::CodePointMapData::from_data, FnInStruct, hidden)]
23    #[diplomat::rust_link(
24        icu::properties::maps::CodePointMapData::try_into_converted,
25        FnInStruct,
26        hidden
27    )]
28    #[diplomat::rust_link(icu::properties::maps::CodePointMapDataBorrowed, Struct)]
29    pub struct ICU4XCodePointMapData8(maps::CodePointMapData<u8>);
30
31    fn convert_8<P: TrieValue>(data: maps::CodePointMapData<P>) -> Box<ICU4XCodePointMapData8> {
32        #[allow(clippy::unwrap_used)] // infallible for the chosen properties
33        Box::new(ICU4XCodePointMapData8(
34            data.try_into_converted().map_err(|_| ()).unwrap(),
35        ))
36    }
37
38    impl ICU4XCodePointMapData8 {
39        /// Gets the value for a code point.
40        #[diplomat::rust_link(icu::properties::maps::CodePointMapDataBorrowed::get, FnInStruct)]
41        #[diplomat::attr(supports = indexing, indexer)]
42        pub fn get(&self, cp: DiplomatChar) -> u8 {
43            self.0.as_borrowed().get32(cp)
44        }
45
46        /// Gets the value for a code point (specified as a 32 bit integer, in UTF-32)
47        #[diplomat::rust_link(
48            icu::properties::maps::CodePointMapDataBorrowed::get32,
49            FnInStruct,
50            hidden
51        )]
52        #[diplomat::attr(dart, disable)]
53        pub fn get32(&self, cp: u32) -> u8 {
54            self.get(cp)
55        }
56
57        /// Converts a general category to its corresponding mask value
58        ///
59        /// Nonexistent general categories will map to the empty mask
60        #[diplomat::rust_link(icu::properties::GeneralCategoryGroup, Struct)]
61        pub fn general_category_to_mask(gc: u8) -> u32 {
62            if let Ok(gc) = GeneralCategory::try_from(gc) {
63                let group: GeneralCategoryGroup = gc.into();
64                group.into()
65            } else {
66                0
67            }
68        }
69
70        /// Produces an iterator over ranges of code points that map to `value`
71        #[diplomat::rust_link(
72            icu::properties::maps::CodePointMapDataBorrowed::iter_ranges_for_value,
73            FnInStruct
74        )]
75        pub fn iter_ranges_for_value<'a>(&'a self, value: u8) -> Box<CodePointRangeIterator<'a>> {
76            Box::new(CodePointRangeIterator(Box::new(
77                self.0.as_borrowed().iter_ranges_for_value(value),
78            )))
79        }
80
81        /// Produces an iterator over ranges of code points that do not map to `value`
82        #[diplomat::rust_link(
83            icu::properties::maps::CodePointMapDataBorrowed::iter_ranges_for_value_complemented,
84            FnInStruct
85        )]
86        pub fn iter_ranges_for_value_complemented<'a>(
87            &'a self,
88            value: u8,
89        ) -> Box<CodePointRangeIterator<'a>> {
90            Box::new(CodePointRangeIterator(Box::new(
91                self.0
92                    .as_borrowed()
93                    .iter_ranges_for_value_complemented(value),
94            )))
95        }
96
97        /// Given a mask value (the nth bit marks property value = n), produce an iterator over ranges of code points
98        /// whose property values are contained in the mask.
99        ///
100        /// The main mask property supported is that for General_Category, which can be obtained via `general_category_to_mask()` or
101        /// by using `ICU4XGeneralCategoryNameToMaskMapper`
102        ///
103        /// Should only be used on maps for properties with values less than 32 (like Generak_Category),
104        /// other maps will have unpredictable results
105        #[diplomat::rust_link(
106            icu::properties::maps::CodePointMapDataBorrowed::iter_ranges_for_group,
107            FnInStruct
108        )]
109        pub fn iter_ranges_for_mask<'a>(&'a self, mask: u32) -> Box<CodePointRangeIterator<'a>> {
110            let ranges = self
111                .0
112                .as_borrowed()
113                .iter_ranges_mapped(move |v| {
114                    let val_mask = 1_u32.checked_shl(v.into()).unwrap_or(0);
115                    val_mask & mask != 0
116                })
117                .filter(|v| v.value)
118                .map(|v| v.range);
119            Box::new(CodePointRangeIterator(Box::new(ranges)))
120        }
121
122        /// Gets a [`ICU4XCodePointSetData`] representing all entries in this map that map to the given value
123        #[diplomat::rust_link(
124            icu::properties::maps::CodePointMapDataBorrowed::get_set_for_value,
125            FnInStruct
126        )]
127        pub fn get_set_for_value(&self, value: u8) -> Box<ICU4XCodePointSetData> {
128            Box::new(ICU4XCodePointSetData(
129                self.0.as_borrowed().get_set_for_value(value),
130            ))
131        }
132
133        #[diplomat::rust_link(icu::properties::maps::general_category, Fn)]
134        #[diplomat::rust_link(icu::properties::maps::load_general_category, Fn, hidden)]
135        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "general_category")]
136        pub fn load_general_category(
137            provider: &ICU4XDataProvider,
138        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
139            Ok(convert_8(call_constructor_unstable!(
140                maps::general_category [r => Ok(r.static_to_owned())],
141                maps::load_general_category,
142                provider,
143            )?))
144        }
145
146        #[diplomat::rust_link(icu::properties::maps::bidi_class, Fn)]
147        #[diplomat::rust_link(icu::properties::maps::load_bidi_class, Fn, hidden)]
148        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "bidi_class")]
149        pub fn load_bidi_class(
150            provider: &ICU4XDataProvider,
151        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
152            Ok(convert_8(call_constructor_unstable!(
153                maps::bidi_class [r => Ok(r.static_to_owned())],
154                maps::load_bidi_class,
155                provider,
156            )?))
157        }
158
159        #[diplomat::rust_link(icu::properties::maps::east_asian_width, Fn)]
160        #[diplomat::rust_link(icu::properties::maps::load_east_asian_width, Fn, hidden)]
161        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "east_asian_width")]
162        pub fn load_east_asian_width(
163            provider: &ICU4XDataProvider,
164        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
165            Ok(convert_8(call_constructor_unstable!(
166                maps::east_asian_width [r => Ok(r.static_to_owned())],
167                maps::load_east_asian_width,
168                provider,
169            )?))
170        }
171
172        #[diplomat::rust_link(icu::properties::maps::hangul_syllable_type, Fn)]
173        #[diplomat::rust_link(icu::properties::maps::load_hangul_syllable_type, Fn, hidden)]
174        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "hangul_syllable_type")]
175        pub fn load_hangul_syllable_type(
176            provider: &ICU4XDataProvider,
177        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
178            Ok(convert_8(call_constructor_unstable!(
179                maps::hangul_syllable_type [r => Ok(r.static_to_owned())],
180                maps::load_hangul_syllable_type,
181                provider,
182            )?))
183        }
184
185        #[diplomat::rust_link(icu::properties::maps::indic_syllabic_category, Fn)]
186        #[diplomat::rust_link(icu::properties::maps::load_indic_syllabic_category, Fn, hidden)]
187        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "indic_syllabic_category")]
188        pub fn load_indic_syllabic_category(
189            provider: &ICU4XDataProvider,
190        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
191            Ok(convert_8(call_constructor_unstable!(
192                maps::indic_syllabic_category [r => Ok(r.static_to_owned())],
193                maps::load_indic_syllabic_category,
194                provider,
195            )?))
196        }
197
198        #[diplomat::rust_link(icu::properties::maps::line_break, Fn)]
199        #[diplomat::rust_link(icu::properties::maps::load_line_break, Fn, hidden)]
200        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "line_break")]
201        pub fn load_line_break(
202            provider: &ICU4XDataProvider,
203        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
204            Ok(convert_8(call_constructor_unstable!(
205                maps::line_break [r => Ok(r.static_to_owned())],
206                maps::load_line_break,
207                provider,
208            )?))
209        }
210
211        #[diplomat::rust_link(icu::properties::maps::grapheme_cluster_break, Fn)]
212        #[diplomat::rust_link(icu::properties::maps::load_grapheme_cluster_break, Fn, hidden)]
213        pub fn try_grapheme_cluster_break(
214            provider: &ICU4XDataProvider,
215        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
216            Ok(convert_8(call_constructor_unstable!(
217                maps::grapheme_cluster_break [r => Ok(r.static_to_owned())],
218                maps::load_grapheme_cluster_break,
219                provider,
220            )?))
221        }
222
223        #[diplomat::rust_link(icu::properties::maps::word_break, Fn)]
224        #[diplomat::rust_link(icu::properties::maps::load_word_break, Fn, hidden)]
225        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "word_break")]
226        pub fn load_word_break(
227            provider: &ICU4XDataProvider,
228        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
229            Ok(convert_8(call_constructor_unstable!(
230                maps::word_break [r => Ok(r.static_to_owned())],
231                maps::load_word_break,
232                provider,
233            )?))
234        }
235
236        #[diplomat::rust_link(icu::properties::maps::sentence_break, Fn)]
237        #[diplomat::rust_link(icu::properties::maps::load_sentence_break, Fn, hidden)]
238        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "sentence_break")]
239        pub fn load_sentence_break(
240            provider: &ICU4XDataProvider,
241        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
242            Ok(convert_8(call_constructor_unstable!(
243                maps::sentence_break [r => Ok(r.static_to_owned())],
244                maps::load_sentence_break,
245                provider,
246            )?))
247        }
248
249        #[diplomat::rust_link(icu::properties::maps::joining_type, Fn)]
250        #[diplomat::rust_link(icu::properties::maps::load_joining_type, Fn, hidden)]
251        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "joining_type")]
252        pub fn load_joining_type(
253            provider: &ICU4XDataProvider,
254        ) -> Result<Box<ICU4XCodePointMapData8>, ICU4XError> {
255            Ok(convert_8(call_constructor_unstable!(
256                maps::joining_type [r => Ok(r.static_to_owned())],
257                maps::load_joining_type,
258                provider,
259            )?))
260        }
261    }
262
263    #[diplomat::opaque]
264    /// An ICU4X Unicode Map Property object, capable of querying whether a code point (key) to obtain the Unicode property value, for a specific Unicode property.
265    ///
266    /// For properties whose values fit into 16 bits.
267    #[diplomat::rust_link(icu::properties, Mod)]
268    #[diplomat::rust_link(icu::properties::maps::CodePointMapData, Struct)]
269    #[diplomat::rust_link(icu::properties::maps::CodePointMapDataBorrowed, Struct)]
270    pub struct ICU4XCodePointMapData16(maps::CodePointMapData<u16>);
271
272    impl ICU4XCodePointMapData16 {
273        /// Gets the value for a code point.
274        #[diplomat::rust_link(icu::properties::maps::CodePointMapDataBorrowed::get, FnInStruct)]
275        #[diplomat::attr(supports = indexing, indexer)]
276        pub fn get(&self, cp: DiplomatChar) -> u16 {
277            self.0.as_borrowed().get32(cp)
278        }
279
280        /// Gets the value for a code point (specified as a 32 bit integer, in UTF-32)
281        #[diplomat::rust_link(
282            icu::properties::maps::CodePointMapDataBorrowed::get32,
283            FnInStruct,
284            hidden
285        )]
286        #[diplomat::attr(dart, disable)]
287        pub fn get32(&self, cp: u32) -> u16 {
288            self.get(cp)
289        }
290
291        /// Produces an iterator over ranges of code points that map to `value`
292        #[diplomat::rust_link(
293            icu::properties::maps::CodePointMapDataBorrowed::iter_ranges_for_value,
294            FnInStruct
295        )]
296        pub fn iter_ranges_for_value<'a>(&'a self, value: u16) -> Box<CodePointRangeIterator<'a>> {
297            Box::new(CodePointRangeIterator(Box::new(
298                self.0.as_borrowed().iter_ranges_for_value(value),
299            )))
300        }
301
302        /// Produces an iterator over ranges of code points that do not map to `value`
303        #[diplomat::rust_link(
304            icu::properties::maps::CodePointMapDataBorrowed::iter_ranges_for_value_complemented,
305            FnInStruct
306        )]
307        pub fn iter_ranges_for_value_complemented<'a>(
308            &'a self,
309            value: u16,
310        ) -> Box<CodePointRangeIterator<'a>> {
311            Box::new(CodePointRangeIterator(Box::new(
312                self.0
313                    .as_borrowed()
314                    .iter_ranges_for_value_complemented(value),
315            )))
316        }
317
318        /// Gets a [`ICU4XCodePointSetData`] representing all entries in this map that map to the given value
319        #[diplomat::rust_link(
320            icu::properties::maps::CodePointMapDataBorrowed::get_set_for_value,
321            FnInStruct
322        )]
323        pub fn get_set_for_value(&self, value: u16) -> Box<ICU4XCodePointSetData> {
324            Box::new(ICU4XCodePointSetData(
325                self.0.as_borrowed().get_set_for_value(value),
326            ))
327        }
328
329        #[diplomat::rust_link(icu::properties::maps::script, Fn)]
330        #[diplomat::rust_link(icu::properties::maps::load_script, Fn, hidden)]
331        #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "script")]
332        pub fn load_script(
333            provider: &ICU4XDataProvider,
334        ) -> Result<Box<ICU4XCodePointMapData16>, ICU4XError> {
335            #[allow(clippy::unwrap_used)] // script is a 16-bit property
336            Ok(Box::new(ICU4XCodePointMapData16(
337                call_constructor_unstable!(
338                    maps::script [r => Ok(r.static_to_owned())],
339                    maps::load_script,
340                    provider,
341                )?
342                .try_into_converted()
343                .map_err(|_| ())
344                .unwrap(),
345            )))
346        }
347    }
348}