Skip to content

Commit 5dd93c4

Browse files
committed
model BidiAuxiliaryProperties as an EnumeratedProperty
1 parent 82ff849 commit 5dd93c4

File tree

19 files changed

+1115
-1528
lines changed

19 files changed

+1115
-1528
lines changed

components/properties/src/bidi.rs

+49-199
Original file line numberDiff line numberDiff line change
@@ -2,218 +2,68 @@
22
// called LICENSE at the top level of the ICU4X source tree
33
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
44

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::{
14-
BidiAuxiliaryPropertiesV1, BidiAuxiliaryPropertiesV1Marker, CheckedBidiPairedBracketType,
15-
};
16-
17-
use icu_provider::prelude::*;
18-
19-
/// A wrapper around certain Bidi properties data.
20-
///
21-
/// Most useful methods are on [`BidiAuxiliaryPropertiesBorrowed`] obtained by calling [`BidiAuxiliaryProperties::as_borrowed()`]
22-
#[derive(Debug)]
23-
pub struct BidiAuxiliaryProperties {
24-
data: DataPayload<BidiAuxiliaryPropertiesV1Marker>,
25-
}
26-
27-
impl BidiAuxiliaryProperties {
28-
/// Creates a [`BidiAuxiliaryPropertiesV1`] struct that represents the data for certain
29-
/// Bidi properties.
30-
///
31-
/// ✨ *Enabled with the `compiled_data` Cargo feature.*
32-
///
33-
/// [📚 Help choosing a constructor](icu_provider::constructors)
34-
///
35-
/// # Examples
36-
/// ```
37-
/// use icu::properties::bidi::BidiAuxiliaryProperties;
38-
///
39-
/// let bidi_data = BidiAuxiliaryProperties::new();
40-
///
41-
/// let open_paren = bidi_data.get32_mirroring_props('(' as u32);
42-
/// assert_eq!(open_paren.mirroring_glyph, Some(')'));
43-
/// assert_eq!(open_paren.mirrored, true);
44-
/// ```
45-
#[cfg(feature = "compiled_data")]
46-
#[allow(clippy::new_ret_no_self)]
47-
pub const fn new() -> BidiAuxiliaryPropertiesBorrowed<'static> {
48-
BidiAuxiliaryPropertiesBorrowed {
49-
data: crate::provider::Baked::SINGLETON_BIDI_AUXILIARY_PROPERTIES_V1_MARKER,
50-
}
51-
}
52-
53-
icu_provider::gen_any_buffer_data_constructors!(
54-
() -> result: Result<BidiAuxiliaryProperties, DataError>,
55-
functions: [
56-
new: skip,
57-
try_new_with_any_provider,
58-
try_new_with_buffer_provider,
59-
try_new_unstable,
60-
Self
61-
]
62-
);
63-
64-
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::new)]
65-
pub fn try_new_unstable(
66-
provider: &(impl DataProvider<BidiAuxiliaryPropertiesV1Marker> + ?Sized),
67-
) -> Result<BidiAuxiliaryProperties, DataError> {
68-
Ok(BidiAuxiliaryProperties::from_data(
69-
provider.load(Default::default())?.payload,
70-
))
71-
}
72-
73-
/// Construct a borrowed version of this type that can be queried.
74-
///
75-
/// This avoids a potential small underlying cost per API call by consolidating it
76-
/// up front.
77-
#[inline]
78-
pub fn as_borrowed(&self) -> BidiAuxiliaryPropertiesBorrowed<'_> {
79-
BidiAuxiliaryPropertiesBorrowed {
80-
data: self.data.get(),
81-
}
82-
}
83-
84-
/// Construct a new one from loaded data
85-
///
86-
/// Typically it is preferable to use getters like [`bidi_auxiliary_properties()`] instead
87-
pub(crate) fn from_data(data: DataPayload<BidiAuxiliaryPropertiesV1Marker>) -> Self {
88-
Self { data }
89-
}
90-
}
91-
92-
/// This struct represents the properties Bidi_Mirrored and Bidi_Mirroring_Glyph.
93-
/// If Bidi_Mirroring_Glyph is not defined for a code point, then the value in the
94-
/// struct is `None`.
95-
#[derive(Debug, Eq, PartialEq)]
5+
use crate::{props::EnumeratedProperty, provider::BidiMirroringGlyphV1Marker};
6+
use icu_collections::codepointtrie::TrieValue;
7+
use zerovec::ule::{AsULE, RawBytesULE};
8+
9+
/// This is a bitpacked combination of the `Bidi_Mirroring_Glyph`,
10+
/// `Bidi_Mirrored`, and `Bidi_Paired_Bracket_Type` properties.
11+
#[derive(Debug, Eq, PartialEq, Clone, Copy, Default)]
12+
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
13+
#[cfg_attr(feature = "datagen", databake(path = icu_properties::bidi))]
14+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
9615
#[non_exhaustive]
97-
pub struct BidiMirroringProperties {
98-
/// Represents the Bidi_Mirroring_Glyph property value
16+
pub struct BidiMirroringGlyph {
17+
/// The mirroring glyph
9918
pub mirroring_glyph: Option<char>,
100-
/// Represents the Bidi_Mirrored property value
19+
/// Whether the glyph is mirrored
10120
pub mirrored: bool,
21+
/// The paired bracket type
22+
pub paired_bracket_type: BidiPairedBracketType,
10223
}
10324

104-
/// The enum represents Bidi_Paired_Bracket_Type, the char represents Bidi_Paired_Bracket.
105-
/// Bidi_Paired_Bracket has a value of `None` when Bidi_Paired_Bracket_Type is `None`.
106-
#[derive(Debug, Eq, PartialEq)]
107-
#[non_exhaustive]
108-
pub enum BidiPairingProperties {
109-
/// Represents Bidi_Paired_Bracket_Type=Open, and the Bidi_Paired_Bracket value for that code point.
110-
Open(char),
111-
/// Represents Bidi_Paired_Bracket_Type=Close, and the Bidi_Paired_Bracket value for that code point.
112-
Close(char),
113-
/// Represents Bidi_Paired_Bracket_Type=None, which cooccurs with Bidi_Paired_Bracket
114-
/// being undefined for that code point.
115-
None,
25+
impl EnumeratedProperty for BidiMirroringGlyph {
26+
type DataMarker = BidiMirroringGlyphV1Marker;
27+
#[cfg(feature = "compiled_data")]
28+
const SINGLETON: &'static crate::provider::PropertyCodePointMapV1<'static, Self> =
29+
crate::provider::Baked::SINGLETON_BIDI_MIRRORING_GLYPH_V1_MARKER;
11630
}
11731

118-
/// A borrowed wrapper around Bidi properties data, returned by
119-
/// [`BidiAuxiliaryProperties::as_borrowed()`]. More efficient to query.
120-
#[derive(Debug)]
121-
pub struct BidiAuxiliaryPropertiesBorrowed<'a> {
122-
data: &'a BidiAuxiliaryPropertiesV1<'a>,
123-
}
32+
impl crate::private::Sealed for BidiMirroringGlyph {}
12433

125-
impl<'a> BidiAuxiliaryPropertiesBorrowed<'a> {
126-
// The source data coming from icuexportdata will use 0 to represent the
127-
// property value in cases for which the Bidi_Mirroring_Glyph property value
128-
// of a code point is undefined. Since Rust types can be more expressive, we
129-
// should represent these cases as None.
130-
fn convert_mirroring_glyph_data(trie_data_char: char) -> Option<char> {
131-
if trie_data_char as u32 == 0 {
132-
None
133-
} else {
134-
Some(trie_data_char)
135-
}
136-
}
34+
impl AsULE for BidiMirroringGlyph {
35+
type ULE = zerovec::ule::RawBytesULE<3>;
13736

138-
/// Return a struct for the given code point representing Bidi mirroring-related
139-
/// property values. See [`BidiMirroringProperties`].
140-
///
141-
/// # Examples
142-
/// ```
143-
/// use icu::properties::bidi::BidiAuxiliaryProperties;
144-
///
145-
/// let bidi_data = BidiAuxiliaryProperties::new();
146-
///
147-
/// let open_paren = bidi_data.get32_mirroring_props('(' as u32);
148-
/// assert_eq!(open_paren.mirroring_glyph, Some(')'));
149-
/// assert_eq!(open_paren.mirrored, true);
150-
/// let close_paren = bidi_data.get32_mirroring_props(')' as u32);
151-
/// assert_eq!(close_paren.mirroring_glyph, Some('('));
152-
/// assert_eq!(close_paren.mirrored, true);
153-
/// let open_angle_bracket = bidi_data.get32_mirroring_props('<' as u32);
154-
/// assert_eq!(open_angle_bracket.mirroring_glyph, Some('>'));
155-
/// assert_eq!(open_angle_bracket.mirrored, true);
156-
/// let close_angle_bracket = bidi_data.get32_mirroring_props('>' as u32);
157-
/// assert_eq!(close_angle_bracket.mirroring_glyph, Some('<'));
158-
/// assert_eq!(close_angle_bracket.mirrored, true);
159-
/// let three = bidi_data.get32_mirroring_props('3' as u32);
160-
/// assert_eq!(three.mirroring_glyph, None);
161-
/// assert_eq!(three.mirrored, false);
162-
/// ```
163-
pub fn get32_mirroring_props(&self, code_point: u32) -> BidiMirroringProperties {
164-
let BidiAuxiliaryPropertiesV1::CodePointTrie(trie) = self.data;
165-
let bidi_aux_props = trie.get32(code_point);
166-
let mirroring_glyph_opt =
167-
Self::convert_mirroring_glyph_data(bidi_aux_props.mirroring_glyph);
168-
BidiMirroringProperties {
169-
mirroring_glyph: mirroring_glyph_opt,
170-
mirrored: bidi_aux_props.mirrored,
171-
}
37+
fn to_unaligned(self) -> Self::ULE {
38+
let [a, b, c, _] = TrieValue::to_u32(self).to_le_bytes();
39+
RawBytesULE([a, b, c])
17240
}
173-
174-
/// Return a struct for the given code point representing Bidi bracket
175-
/// pairing-related property values. See [`BidiPairingProperties`]
176-
///
177-
/// # Examples
178-
/// ```
179-
/// use icu::properties::bidi::{BidiAuxiliaryProperties, BidiPairingProperties};
180-
///
181-
/// let bidi_data = BidiAuxiliaryProperties::new();
182-
///
183-
/// let open_paren = bidi_data.get32_pairing_props('(' as u32);
184-
/// assert_eq!(open_paren, BidiPairingProperties::Open(')'));
185-
/// let close_paren = bidi_data.get32_pairing_props(')' as u32);
186-
/// assert_eq!(close_paren, BidiPairingProperties::Close('('));
187-
/// let open_angle_bracket = bidi_data.get32_pairing_props('<' as u32);
188-
/// assert_eq!(open_angle_bracket, BidiPairingProperties::None);
189-
/// let close_angle_bracket = bidi_data.get32_pairing_props('>' as u32);
190-
/// assert_eq!(close_angle_bracket, BidiPairingProperties::None);
191-
/// let three = bidi_data.get32_pairing_props('3' as u32);
192-
/// assert_eq!(three, BidiPairingProperties::None);
193-
/// ```
194-
pub fn get32_pairing_props(&self, code_point: u32) -> BidiPairingProperties {
195-
let BidiAuxiliaryPropertiesV1::CodePointTrie(trie) = self.data;
196-
let bidi_aux_props = trie.get32(code_point);
197-
let mirroring_glyph = bidi_aux_props.mirroring_glyph;
198-
let paired_bracket_type = bidi_aux_props.paired_bracket_type;
199-
match paired_bracket_type {
200-
CheckedBidiPairedBracketType::Open => BidiPairingProperties::Open(mirroring_glyph),
201-
CheckedBidiPairedBracketType::Close => BidiPairingProperties::Close(mirroring_glyph),
202-
_ => BidiPairingProperties::None,
203-
}
41+
fn from_unaligned(unaligned: Self::ULE) -> Self {
42+
let [a, b, c] = unaligned.0;
43+
TrieValue::try_from_u32(u32::from_le_bytes([a, b, c, 0])).unwrap_or_default()
20444
}
20545
}
20646

207-
impl BidiAuxiliaryPropertiesBorrowed<'static> {
208-
/// Cheaply converts a [`BidiAuxiliaryPropertiesBorrowed<'static>`] into a [`BidiAuxiliaryProperties`].
209-
///
210-
/// Note: Due to branching and indirection, using [`BidiAuxiliaryProperties`] might inhibit some
211-
/// compile-time optimizations that are possible with [`BidiAuxiliaryPropertiesBorrowed`].
212-
pub const fn static_to_owned(self) -> BidiAuxiliaryProperties {
213-
BidiAuxiliaryProperties {
214-
data: DataPayload::from_static_ref(self.data),
215-
}
216-
}
47+
/// The enum represents Bidi_Paired_Bracket_Type.
48+
///
49+
/// It does not implement [`EnumeratedProperty`], instead it can be obtained
50+
/// through the bitpacked [`BidiMirroringGlyph`] property.
51+
///
52+
/// If you have a use case this property without also needing the [`BidiMirroringGlyph`]
53+
/// property, and need to optimize data size, please file an issue.
54+
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
55+
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
56+
#[cfg_attr(feature = "datagen", databake(path = icu_properties::bidi))]
57+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
58+
#[non_exhaustive]
59+
pub enum BidiPairedBracketType {
60+
/// Represents Bidi_Paired_Bracket_Type=Open.
61+
Open,
62+
/// Represents Bidi_Paired_Bracket_Type=Close.
63+
Close,
64+
/// Represents Bidi_Paired_Bracket_Type=None.
65+
#[default]
66+
None,
21767
}
21868

21969
/// Implements [`unicode_bidi::BidiDataSource`] on [`CodePointMapDataBorrowed<BidiClass>`](crate::CodePointMapDataBorrowed).

components/properties/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ pub use names::{
8383
mod runtime;
8484
pub use runtime::UnicodeProperty;
8585

86-
pub mod bidi;
8786
// NOTE: The Pernosco debugger has special knowledge
8887
// of the `CanonicalCombiningClass` struct inside the `props`
8988
// module. Please do not change the crate-module-qualified
@@ -92,6 +91,7 @@ pub mod props;
9291
pub mod provider;
9392
pub mod script;
9493

94+
mod bidi;
9595
mod trievalue;
9696

9797
mod private {

components/properties/src/props.rs

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
2020
pub use crate::names::{NamedEnumeratedProperty, ParseableEnumeratedProperty};
2121

22+
pub use crate::bidi::{BidiMirroringGlyph, BidiPairedBracketType};
23+
2224
/// See [`test_enumerated_property_completeness`] for usage.
2325
/// Example input:
2426
/// ```ignore

components/properties/src/provider.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
//!
1616
//! Read more about data providers: [`icu_provider`]
1717
18-
pub mod bidi;
1918
pub mod names;
2019

2120
pub use names::{
@@ -40,18 +39,15 @@ pub use names::{
4039
WordBreakValueToShortNameV1Marker,
4140
};
4241

42+
use crate::bidi::BidiMirroringGlyph;
4343
pub use crate::props::gc::GeneralCategoryULE;
44-
pub use bidi::BidiAuxiliaryPropertiesV1Marker;
45-
4644
use crate::script::ScriptWithExt;
47-
4845
use core::ops::RangeInclusive;
4946
use icu_collections::codepointinvlist::CodePointInversionList;
5047
use icu_collections::codepointinvliststringlist::CodePointInversionListAndStringList;
5148
use icu_collections::codepointtrie::{CodePointMapRange, CodePointTrie, TrieValue};
5249
use icu_provider::prelude::*;
5350
use zerofrom::ZeroFrom;
54-
5551
use zerovec::{ule::UleError, VarZeroVec, ZeroSlice};
5652

5753
#[cfg(feature = "compiled_data")]
@@ -78,13 +74,13 @@ const _: () = {
7874
impl_alphabetic_v1_marker!(Baked);
7975
impl_ascii_hex_digit_v1_marker!(Baked);
8076
impl_basic_emoji_v1_marker!(Baked);
81-
impl_bidi_auxiliary_properties_v1_marker!(Baked);
8277
impl_bidi_class_name_to_value_v1_marker!(Baked);
8378
impl_bidi_class_v1_marker!(Baked);
8479
impl_bidi_class_value_to_long_name_v1_marker!(Baked);
8580
impl_bidi_class_value_to_short_name_v1_marker!(Baked);
8681
impl_bidi_control_v1_marker!(Baked);
8782
impl_bidi_mirrored_v1_marker!(Baked);
83+
impl_bidi_mirroring_glyph_v1_marker!(Baked);
8884
impl_blank_v1_marker!(Baked);
8985
impl_canonical_combining_class_name_to_value_v1_marker!(Baked);
9086
impl_canonical_combining_class_v1_marker!(Baked);
@@ -199,9 +195,9 @@ pub const MARKERS: &[DataMarkerInfo] = &[
199195
AlphabeticV1Marker::INFO,
200196
AsciiHexDigitV1Marker::INFO,
201197
BasicEmojiV1Marker::INFO,
202-
bidi::BidiAuxiliaryPropertiesV1Marker::INFO,
203198
BidiControlV1Marker::INFO,
204199
BidiMirroredV1Marker::INFO,
200+
BidiMirroringGlyphV1Marker::INFO,
205201
BlankV1Marker::INFO,
206202
CasedV1Marker::INFO,
207203
CaseIgnorableV1Marker::INFO,
@@ -536,6 +532,11 @@ data_struct_generic!(
536532
marker(ScriptV1Marker, Script, "props/sc@1"),
537533
marker(SentenceBreakV1Marker, SentenceBreak, "props/SB@1"),
538534
marker(WordBreakV1Marker, WordBreak, "props/WB@1"),
535+
marker(
536+
BidiMirroringGlyphV1Marker,
537+
BidiMirroringGlyph,
538+
"props/Bidi_G@1"
539+
),
539540
);
540541

541542
// See CodePointMapData for documentation of these functions

0 commit comments

Comments
 (0)