Coverage Report

Created: 2026-01-25 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/icu_properties-2.1.2/src/bidi.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
use crate::{props::EnumeratedProperty, provider::PropertyEnumBidiMirroringGlyphV1};
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::props))]
14
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
15
#[allow(clippy::exhaustive_structs)] // needed for baked construction
16
pub struct BidiMirroringGlyph {
17
    /// The mirroring glyph
18
    pub mirroring_glyph: Option<char>,
19
    /// Whether the glyph is mirrored
20
    pub mirrored: bool,
21
    /// The paired bracket type
22
    pub paired_bracket_type: BidiPairedBracketType,
23
}
24
25
impl EnumeratedProperty for BidiMirroringGlyph {
26
    type DataMarker = PropertyEnumBidiMirroringGlyphV1;
27
    #[cfg(feature = "compiled_data")]
28
    const SINGLETON: &'static crate::provider::PropertyCodePointMap<'static, Self> =
29
        crate::provider::Baked::SINGLETON_PROPERTY_ENUM_BIDI_MIRRORING_GLYPH_V1;
30
    const NAME: &'static [u8] = b"Bidi_Mirroring_Glyph";
31
    const SHORT_NAME: &'static [u8] = b"bmg";
32
}
33
34
impl crate::private::Sealed for BidiMirroringGlyph {}
35
36
impl AsULE for BidiMirroringGlyph {
37
    type ULE = zerovec::ule::RawBytesULE<3>;
38
39
0
    fn to_unaligned(self) -> Self::ULE {
40
0
        let [a, b, c, _] = TrieValue::to_u32(self).to_le_bytes();
41
0
        RawBytesULE([a, b, c])
42
0
    }
43
0
    fn from_unaligned(unaligned: Self::ULE) -> Self {
44
0
        let [a, b, c] = unaligned.0;
45
0
        TrieValue::try_from_u32(u32::from_le_bytes([a, b, c, 0])).unwrap_or_default()
46
0
    }
47
}
48
49
/// The enum represents Bidi_Paired_Bracket_Type.
50
///
51
/// It does not implement [`EnumeratedProperty`], instead it can be obtained
52
/// through the bitpacked [`BidiMirroringGlyph`] property.
53
///
54
/// If you have a use case this property without also needing the [`BidiMirroringGlyph`]
55
/// property, and need to optimize data size, please file an issue.
56
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
57
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
58
#[cfg_attr(feature = "datagen", databake(path = icu_properties::props))]
59
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
60
#[non_exhaustive]
61
pub enum BidiPairedBracketType {
62
    /// Represents Bidi_Paired_Bracket_Type=Open.
63
    Open,
64
    /// Represents Bidi_Paired_Bracket_Type=Close.
65
    Close,
66
    /// Represents Bidi_Paired_Bracket_Type=None.
67
    #[default]
68
    None,
69
}
70
71
#[cfg(feature = "unicode_bidi")]
72
use crate::props::BidiClass;
73
74
/// ✨ *Enabled with the `unicode_bidi` Cargo feature.*
75
///
76
/// # Examples
77
///
78
///```
79
/// use icu::properties::CodePointMapData;
80
/// use icu::properties::props::BidiClass;
81
/// use unicode_bidi::BidiInfo;
82
///
83
/// // This example text is defined using `concat!` because some browsers
84
/// // and text editors have trouble displaying bidi strings.
85
/// let text =  concat!["א", // RTL#1
86
///                     "ב", // RTL#2
87
///                     "ג", // RTL#3
88
///                     "a", // LTR#1
89
///                     "b", // LTR#2
90
///                     "c", // LTR#3
91
///                     ]; //
92
///
93
///
94
/// let bidi_map = CodePointMapData::<BidiClass>::new();
95
///
96
/// // Resolve embedding levels within the text.  Pass `None` to detect the
97
/// // paragraph level automatically.
98
/// let bidi_info = BidiInfo::new_with_data_source(&bidi_map, text, None);
99
///
100
/// // This paragraph has embedding level 1 because its first strong character is RTL.
101
/// assert_eq!(bidi_info.paragraphs.len(), 1);
102
/// let para = &bidi_info.paragraphs[0];
103
/// assert_eq!(para.level.number(), 1);
104
/// assert!(para.level.is_rtl());
105
///
106
/// // Re-ordering is done after wrapping each paragraph into a sequence of
107
/// // lines. For this example, I'll just use a single line that spans the
108
/// // entire paragraph.
109
/// let line = para.range.clone();
110
///
111
/// let display = bidi_info.reorder_line(para, line);
112
/// assert_eq!(display, concat!["a", // LTR#1
113
///                             "b", // LTR#2
114
///                             "c", // LTR#3
115
///                             "ג", // RTL#3
116
///                             "ב", // RTL#2
117
///                             "א", // RTL#1
118
///                             ]);
119
/// ```
120
#[cfg(feature = "unicode_bidi")]
121
impl unicode_bidi::data_source::BidiDataSource for crate::CodePointMapDataBorrowed<'_, BidiClass> {
122
    fn bidi_class(&self, c: char) -> unicode_bidi::BidiClass {
123
        self.get(c).into()
124
    }
125
}
126
127
#[cfg(feature = "unicode_bidi")]
128
impl From<BidiClass> for unicode_bidi::BidiClass {
129
    fn from(value: BidiClass) -> Self {
130
        match value {
131
            BidiClass::LeftToRight => unicode_bidi::BidiClass::L,
132
            BidiClass::RightToLeft => unicode_bidi::BidiClass::R,
133
            BidiClass::EuropeanNumber => unicode_bidi::BidiClass::EN,
134
            BidiClass::EuropeanSeparator => unicode_bidi::BidiClass::ES,
135
            BidiClass::EuropeanTerminator => unicode_bidi::BidiClass::ET,
136
            BidiClass::ArabicNumber => unicode_bidi::BidiClass::AN,
137
            BidiClass::CommonSeparator => unicode_bidi::BidiClass::CS,
138
            BidiClass::ParagraphSeparator => unicode_bidi::BidiClass::B,
139
            BidiClass::SegmentSeparator => unicode_bidi::BidiClass::S,
140
            BidiClass::WhiteSpace => unicode_bidi::BidiClass::WS,
141
            BidiClass::OtherNeutral => unicode_bidi::BidiClass::ON,
142
            BidiClass::LeftToRightEmbedding => unicode_bidi::BidiClass::LRE,
143
            BidiClass::LeftToRightOverride => unicode_bidi::BidiClass::LRO,
144
            BidiClass::ArabicLetter => unicode_bidi::BidiClass::AL,
145
            BidiClass::RightToLeftEmbedding => unicode_bidi::BidiClass::RLE,
146
            BidiClass::RightToLeftOverride => unicode_bidi::BidiClass::RLO,
147
            BidiClass::PopDirectionalFormat => unicode_bidi::BidiClass::PDF,
148
            BidiClass::NonspacingMark => unicode_bidi::BidiClass::NSM,
149
            BidiClass::BoundaryNeutral => unicode_bidi::BidiClass::BN,
150
            BidiClass::FirstStrongIsolate => unicode_bidi::BidiClass::FSI,
151
            BidiClass::LeftToRightIsolate => unicode_bidi::BidiClass::LRI,
152
            BidiClass::RightToLeftIsolate => unicode_bidi::BidiClass::RLI,
153
            BidiClass::PopDirectionalIsolate => unicode_bidi::BidiClass::PDI,
154
            // This must not happen.
155
            _ => unicode_bidi::BidiClass::ON,
156
        }
157
    }
158
}
159
160
#[cfg(feature = "unicode_bidi")]
161
impl From<unicode_bidi::BidiClass> for BidiClass {
162
    fn from(value: unicode_bidi::BidiClass) -> Self {
163
        match value {
164
            unicode_bidi::BidiClass::L => BidiClass::LeftToRight,
165
            unicode_bidi::BidiClass::R => BidiClass::RightToLeft,
166
            unicode_bidi::BidiClass::EN => BidiClass::EuropeanNumber,
167
            unicode_bidi::BidiClass::ES => BidiClass::EuropeanSeparator,
168
            unicode_bidi::BidiClass::ET => BidiClass::EuropeanTerminator,
169
            unicode_bidi::BidiClass::AN => BidiClass::ArabicNumber,
170
            unicode_bidi::BidiClass::CS => BidiClass::CommonSeparator,
171
            unicode_bidi::BidiClass::B => BidiClass::ParagraphSeparator,
172
            unicode_bidi::BidiClass::S => BidiClass::SegmentSeparator,
173
            unicode_bidi::BidiClass::WS => BidiClass::WhiteSpace,
174
            unicode_bidi::BidiClass::ON => BidiClass::OtherNeutral,
175
            unicode_bidi::BidiClass::LRE => BidiClass::LeftToRightEmbedding,
176
            unicode_bidi::BidiClass::LRO => BidiClass::LeftToRightOverride,
177
            unicode_bidi::BidiClass::AL => BidiClass::ArabicLetter,
178
            unicode_bidi::BidiClass::RLE => BidiClass::RightToLeftEmbedding,
179
            unicode_bidi::BidiClass::RLO => BidiClass::RightToLeftOverride,
180
            unicode_bidi::BidiClass::PDF => BidiClass::PopDirectionalFormat,
181
            unicode_bidi::BidiClass::NSM => BidiClass::NonspacingMark,
182
            unicode_bidi::BidiClass::BN => BidiClass::BoundaryNeutral,
183
            unicode_bidi::BidiClass::FSI => BidiClass::FirstStrongIsolate,
184
            unicode_bidi::BidiClass::LRI => BidiClass::LeftToRightIsolate,
185
            unicode_bidi::BidiClass::RLI => BidiClass::RightToLeftIsolate,
186
            unicode_bidi::BidiClass::PDI => BidiClass::PopDirectionalIsolate,
187
        }
188
    }
189
}