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 | //! Data and APIs for supporting specific Bidi properties data in an efficient structure. |
6 | //! |
7 | //! Supported properties are: |
8 | //! - `Bidi_Paired_Bracket` |
9 | //! - `Bidi_Paired_Bracket_Type` |
10 | //! - `Bidi_Mirrored` |
11 | //! - `Bidi_Mirroring_Glyph` |
12 | |
13 | use crate::provider::bidi_data::{ |
14 | BidiAuxiliaryPropertiesV1, BidiAuxiliaryPropertiesV1Marker, CheckedBidiPairedBracketType, |
15 | }; |
16 | use crate::PropertiesError; |
17 | |
18 | use icu_provider::prelude::*; |
19 | |
20 | /// A wrapper around certain Bidi properties data. Can be obtained via [`bidi_auxiliary_properties()`] and |
21 | /// related getters. |
22 | /// |
23 | /// Most useful methods are on [`BidiAuxiliaryPropertiesBorrowed`] obtained by calling [`BidiAuxiliaryProperties::as_borrowed()`] |
24 | #[derive (Debug)] |
25 | pub struct BidiAuxiliaryProperties { |
26 | data: DataPayload<BidiAuxiliaryPropertiesV1Marker>, |
27 | } |
28 | |
29 | impl BidiAuxiliaryProperties { |
30 | /// Construct a borrowed version of this type that can be queried. |
31 | /// |
32 | /// This avoids a potential small underlying cost per API call by consolidating it |
33 | /// up front. |
34 | #[inline ] |
35 | pub fn as_borrowed(&self) -> BidiAuxiliaryPropertiesBorrowed<'_> { |
36 | BidiAuxiliaryPropertiesBorrowed { |
37 | data: self.data.get(), |
38 | } |
39 | } |
40 | |
41 | /// Construct a new one from loaded data |
42 | /// |
43 | /// Typically it is preferable to use getters like [`bidi_auxiliary_properties()`] instead |
44 | pub fn from_data(data: DataPayload<BidiAuxiliaryPropertiesV1Marker>) -> Self { |
45 | Self { data } |
46 | } |
47 | } |
48 | |
49 | /// This struct represents the properties Bidi_Mirrored and Bidi_Mirroring_Glyph. |
50 | /// If Bidi_Mirroring_Glyph is not defined for a code point, then the value in the |
51 | /// struct is `None`. |
52 | #[derive (Debug, Eq, PartialEq)] |
53 | #[non_exhaustive ] |
54 | pub struct BidiMirroringProperties { |
55 | /// Represents the Bidi_Mirroring_Glyph property value |
56 | pub mirroring_glyph: Option<char>, |
57 | /// Represents the Bidi_Mirrored property value |
58 | pub mirrored: bool, |
59 | } |
60 | |
61 | /// The enum represents Bidi_Paired_Bracket_Type, the char represents Bidi_Paired_Bracket. |
62 | /// Bidi_Paired_Bracket has a value of `None` when Bidi_Paired_Bracket_Type is `None`. |
63 | #[derive (Debug, Eq, PartialEq)] |
64 | #[non_exhaustive ] |
65 | pub enum BidiPairingProperties { |
66 | /// Represents Bidi_Paired_Bracket_Type=Open, and the Bidi_Paired_Bracket value for that code point. |
67 | Open(char), |
68 | /// Represents Bidi_Paired_Bracket_Type=Close, and the Bidi_Paired_Bracket value for that code point. |
69 | Close(char), |
70 | /// Represents Bidi_Paired_Bracket_Type=None, which cooccurs with Bidi_Paired_Bracket |
71 | /// being undefined for that code point. |
72 | None, |
73 | } |
74 | |
75 | /// A borrowed wrapper around Bidi properties data, returned by |
76 | /// [`BidiAuxiliaryProperties::as_borrowed()`]. More efficient to query. |
77 | #[derive (Debug)] |
78 | pub struct BidiAuxiliaryPropertiesBorrowed<'a> { |
79 | data: &'a BidiAuxiliaryPropertiesV1<'a>, |
80 | } |
81 | |
82 | impl<'a> BidiAuxiliaryPropertiesBorrowed<'a> { |
83 | // The source data coming from icuexportdata will use 0 to represent the |
84 | // property value in cases for which the Bidi_Mirroring_Glyph property value |
85 | // of a code point is undefined. Since Rust types can be more expressive, we |
86 | // should represent these cases as None. |
87 | fn convert_mirroring_glyph_data(trie_data_char: char) -> Option<char> { |
88 | if trie_data_char as u32 == 0 { |
89 | None |
90 | } else { |
91 | Some(trie_data_char) |
92 | } |
93 | } |
94 | |
95 | /// Return a struct for the given code point representing Bidi mirroring-related |
96 | /// property values. See [`BidiMirroringProperties`]. |
97 | /// |
98 | /// # Examples |
99 | /// ``` |
100 | /// use icu::properties::bidi_data; |
101 | /// |
102 | /// let bidi_data = bidi_data::bidi_auxiliary_properties(); |
103 | /// |
104 | /// let open_paren = bidi_data.get32_mirroring_props('(' as u32); |
105 | /// assert_eq!(open_paren.mirroring_glyph, Some(')' )); |
106 | /// assert_eq!(open_paren.mirrored, true); |
107 | /// let close_paren = bidi_data.get32_mirroring_props(')' as u32); |
108 | /// assert_eq!(close_paren.mirroring_glyph, Some('(' )); |
109 | /// assert_eq!(close_paren.mirrored, true); |
110 | /// let open_angle_bracket = bidi_data.get32_mirroring_props('<' as u32); |
111 | /// assert_eq!(open_angle_bracket.mirroring_glyph, Some('>' )); |
112 | /// assert_eq!(open_angle_bracket.mirrored, true); |
113 | /// let close_angle_bracket = bidi_data.get32_mirroring_props('>' as u32); |
114 | /// assert_eq!(close_angle_bracket.mirroring_glyph, Some('<' )); |
115 | /// assert_eq!(close_angle_bracket.mirrored, true); |
116 | /// let three = bidi_data.get32_mirroring_props('3' as u32); |
117 | /// assert_eq!(three.mirroring_glyph, None); |
118 | /// assert_eq!(three.mirrored, false); |
119 | /// ``` |
120 | pub fn get32_mirroring_props(&self, code_point: u32) -> BidiMirroringProperties { |
121 | let bidi_aux_props = self.data.trie.get32(code_point); |
122 | let mirroring_glyph_opt = |
123 | Self::convert_mirroring_glyph_data(bidi_aux_props.mirroring_glyph); |
124 | BidiMirroringProperties { |
125 | mirroring_glyph: mirroring_glyph_opt, |
126 | mirrored: bidi_aux_props.mirrored, |
127 | } |
128 | } |
129 | |
130 | /// Return a struct for the given code point representing Bidi bracket |
131 | /// pairing-related property values. See [`BidiPairingProperties`] |
132 | /// |
133 | /// # Examples |
134 | /// ``` |
135 | /// use icu::properties::{bidi_data, bidi_data::BidiPairingProperties}; |
136 | /// |
137 | /// let bidi_data = bidi_data::bidi_auxiliary_properties(); |
138 | /// |
139 | /// let open_paren = bidi_data.get32_pairing_props('(' as u32); |
140 | /// assert_eq!(open_paren, BidiPairingProperties::Open(')' )); |
141 | /// let close_paren = bidi_data.get32_pairing_props(')' as u32); |
142 | /// assert_eq!(close_paren, BidiPairingProperties::Close('(' )); |
143 | /// let open_angle_bracket = bidi_data.get32_pairing_props('<' as u32); |
144 | /// assert_eq!(open_angle_bracket, BidiPairingProperties::None); |
145 | /// let close_angle_bracket = bidi_data.get32_pairing_props('>' as u32); |
146 | /// assert_eq!(close_angle_bracket, BidiPairingProperties::None); |
147 | /// let three = bidi_data.get32_pairing_props('3' as u32); |
148 | /// assert_eq!(three, BidiPairingProperties::None); |
149 | /// ``` |
150 | pub fn get32_pairing_props(&self, code_point: u32) -> BidiPairingProperties { |
151 | let bidi_aux_props = self.data.trie.get32(code_point); |
152 | let mirroring_glyph = bidi_aux_props.mirroring_glyph; |
153 | let paired_bracket_type = bidi_aux_props.paired_bracket_type; |
154 | match paired_bracket_type { |
155 | CheckedBidiPairedBracketType::Open => BidiPairingProperties::Open(mirroring_glyph), |
156 | CheckedBidiPairedBracketType::Close => BidiPairingProperties::Close(mirroring_glyph), |
157 | _ => BidiPairingProperties::None, |
158 | } |
159 | } |
160 | } |
161 | |
162 | impl BidiAuxiliaryPropertiesBorrowed<'static> { |
163 | /// Cheaply converts a [`BidiAuxiliaryPropertiesBorrowed<'static>`] into a [`BidiAuxiliaryProperties`]. |
164 | /// |
165 | /// Note: Due to branching and indirection, using [`BidiAuxiliaryProperties`] might inhibit some |
166 | /// compile-time optimizations that are possible with [`BidiAuxiliaryPropertiesBorrowed`]. |
167 | pub const fn static_to_owned(self) -> BidiAuxiliaryProperties { |
168 | BidiAuxiliaryProperties { |
169 | data: DataPayload::from_static_ref(self.data), |
170 | } |
171 | } |
172 | } |
173 | |
174 | /// Creates a [`BidiAuxiliaryPropertiesV1`] struct that represents the data for certain |
175 | /// Bidi properties. |
176 | /// |
177 | /// ✨ *Enabled with the `compiled_data` Cargo feature.* |
178 | /// |
179 | /// [📚 Help choosing a constructor](icu_provider::constructors) |
180 | /// |
181 | /// # Examples |
182 | /// ``` |
183 | /// use icu::properties::bidi_data; |
184 | /// |
185 | /// let bidi_data = bidi_data::bidi_auxiliary_properties(); |
186 | /// |
187 | /// let open_paren = bidi_data.get32_mirroring_props('(' as u32); |
188 | /// assert_eq!(open_paren.mirroring_glyph, Some(')' )); |
189 | /// assert_eq!(open_paren.mirrored, true); |
190 | /// ``` |
191 | #[cfg (feature = "compiled_data" )] |
192 | pub const fn bidi_auxiliary_properties() -> BidiAuxiliaryPropertiesBorrowed<'static> { |
193 | BidiAuxiliaryPropertiesBorrowed { |
194 | data: crate::provider::Baked::SINGLETON_PROPS_BIDIAUXILIARYPROPS_V1, |
195 | } |
196 | } |
197 | |
198 | icu_provider::gen_any_buffer_data_constructors!( |
199 | locale: skip, |
200 | options: skip, |
201 | result: Result<BidiAuxiliaryProperties, PropertiesError>, |
202 | #[cfg (skip)] |
203 | functions: [ |
204 | bidi_auxiliary_properties, |
205 | load_bidi_auxiliary_properties_with_any_provider, |
206 | load_bidi_auxiliary_properties_with_buffer_provider, |
207 | load_bidi_auxiliary_properties_unstable, |
208 | ] |
209 | ); |
210 | |
211 | #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, bidi_auxiliary_properties)] |
212 | pub fn load_bidi_auxiliary_properties_unstable( |
213 | provider: &(impl DataProvider<BidiAuxiliaryPropertiesV1Marker> + ?Sized), |
214 | ) -> Result<BidiAuxiliaryProperties, PropertiesError> { |
215 | Ok(provider |
216 | .load(Default::default()) |
217 | .and_then(DataResponse::take_payload) |
218 | .map(op:BidiAuxiliaryProperties::from_data)?) |
219 | } |
220 | |