• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::BidiMirroringGlyphV1};
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))]
15 #[non_exhaustive]
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 = BidiMirroringGlyphV1;
27     #[cfg(feature = "compiled_data")]
28     const SINGLETON: &'static crate::provider::PropertyCodePointMap<'static, Self> =
29         crate::provider::Baked::SINGLETON_BIDI_MIRRORING_GLYPH_V1;
30     const NAME: &'static [u8] = b"Bidi_Mirroring_Glyph";
31     const SHORT_NAME: &'static [u8] = b"Bidi_Mirroring_Glyph";
32 }
33 
34 impl crate::private::Sealed for BidiMirroringGlyph {}
35 
36 impl AsULE for BidiMirroringGlyph {
37     type ULE = zerovec::ule::RawBytesULE<3>;
38 
to_unaligned(self) -> Self::ULE39     fn to_unaligned(self) -> Self::ULE {
40         let [a, b, c, _] = TrieValue::to_u32(self).to_le_bytes();
41         RawBytesULE([a, b, c])
42     }
from_unaligned(unaligned: Self::ULE) -> Self43     fn from_unaligned(unaligned: Self::ULE) -> Self {
44         let [a, b, c] = unaligned.0;
45         TrieValue::try_from_u32(u32::from_le_bytes([a, b, c, 0])).unwrap_or_default()
46     }
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::bidi))]
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 /// Implements [`unicode_bidi::BidiDataSource`] on [`CodePointMapDataBorrowed<BidiClass>`](crate::CodePointMapDataBorrowed).
72 ///
73 /// ✨ *Enabled with the `unicode_bidi` Cargo feature.*
74 ///
75 /// # Examples
76 ///
77 ///```
78 /// use icu::properties::CodePointMapData;
79 /// use icu::properties::props::BidiClass;
80 /// use unicode_bidi::BidiInfo;
81 ///
82 /// // This example text is defined using `concat!` because some browsers
83 /// // and text editors have trouble displaying bidi strings.
84 /// let text =  concat!["א", // RTL#1
85 ///                     "ב", // RTL#2
86 ///                     "ג", // RTL#3
87 ///                     "a", // LTR#1
88 ///                     "b", // LTR#2
89 ///                     "c", // LTR#3
90 ///                     ]; //
91 ///
92 ///
93 /// let bidi_map = CodePointMapData::<BidiClass>::new();
94 ///
95 /// // Resolve embedding levels within the text.  Pass `None` to detect the
96 /// // paragraph level automatically.
97 /// let bidi_info = BidiInfo::new_with_data_source(&bidi_map, text, None);
98 ///
99 /// // This paragraph has embedding level 1 because its first strong character is RTL.
100 /// assert_eq!(bidi_info.paragraphs.len(), 1);
101 /// let para = &bidi_info.paragraphs[0];
102 /// assert_eq!(para.level.number(), 1);
103 /// assert!(para.level.is_rtl());
104 ///
105 /// // Re-ordering is done after wrapping each paragraph into a sequence of
106 /// // lines. For this example, I'll just use a single line that spans the
107 /// // entire paragraph.
108 /// let line = para.range.clone();
109 ///
110 /// let display = bidi_info.reorder_line(para, line);
111 /// assert_eq!(display, concat!["a", // LTR#1
112 ///                             "b", // LTR#2
113 ///                             "c", // LTR#3
114 ///                             "ג", // RTL#3
115 ///                             "ב", // RTL#2
116 ///                             "א", // RTL#1
117 ///                             ]);
118 /// ```
119 #[cfg(feature = "unicode_bidi")]
120 impl unicode_bidi::data_source::BidiDataSource
121     for crate::CodePointMapDataBorrowed<'_, crate::props::BidiClass>
122 {
bidi_class(&self, c: char) -> unicode_bidi::BidiClass123     fn bidi_class(&self, c: char) -> unicode_bidi::BidiClass {
124         use crate::props::BidiClass;
125         match self.get(c) {
126             BidiClass::LeftToRight => unicode_bidi::BidiClass::L,
127             BidiClass::RightToLeft => unicode_bidi::BidiClass::R,
128             BidiClass::EuropeanNumber => unicode_bidi::BidiClass::EN,
129             BidiClass::EuropeanSeparator => unicode_bidi::BidiClass::ES,
130             BidiClass::EuropeanTerminator => unicode_bidi::BidiClass::ET,
131             BidiClass::ArabicNumber => unicode_bidi::BidiClass::AN,
132             BidiClass::CommonSeparator => unicode_bidi::BidiClass::CS,
133             BidiClass::ParagraphSeparator => unicode_bidi::BidiClass::B,
134             BidiClass::SegmentSeparator => unicode_bidi::BidiClass::S,
135             BidiClass::WhiteSpace => unicode_bidi::BidiClass::WS,
136             BidiClass::OtherNeutral => unicode_bidi::BidiClass::ON,
137             BidiClass::LeftToRightEmbedding => unicode_bidi::BidiClass::LRE,
138             BidiClass::LeftToRightOverride => unicode_bidi::BidiClass::LRO,
139             BidiClass::ArabicLetter => unicode_bidi::BidiClass::AL,
140             BidiClass::RightToLeftEmbedding => unicode_bidi::BidiClass::RLE,
141             BidiClass::RightToLeftOverride => unicode_bidi::BidiClass::RLO,
142             BidiClass::PopDirectionalFormat => unicode_bidi::BidiClass::PDF,
143             BidiClass::NonspacingMark => unicode_bidi::BidiClass::NSM,
144             BidiClass::BoundaryNeutral => unicode_bidi::BidiClass::BN,
145             BidiClass::FirstStrongIsolate => unicode_bidi::BidiClass::FSI,
146             BidiClass::LeftToRightIsolate => unicode_bidi::BidiClass::LRI,
147             BidiClass::RightToLeftIsolate => unicode_bidi::BidiClass::RLI,
148             BidiClass::PopDirectionalIsolate => unicode_bidi::BidiClass::PDI,
149             // This must not happen.
150             _ => unicode_bidi::BidiClass::ON,
151         }
152     }
153 }
154