1 // Copyright 2017 The Servo Project Developers. See the
2 // COPYRIGHT file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9 
10 //! Bidi Embedding Level
11 //!
12 //! See [`Level`](struct.Level.html) for more details.
13 //!
14 //! <http://www.unicode.org/reports/tr9/#BD2>
15 
16 use alloc::string::{String, ToString};
17 use alloc::vec::Vec;
18 use core::convert::{From, Into};
19 use core::slice;
20 
21 use super::char_data::BidiClass;
22 
23 /// Embedding Level
24 ///
25 /// Embedding Levels are numbers between 0 and 126 (inclusive), where even values denote a
26 /// left-to-right (LTR) direction and odd values a right-to-left (RTL) direction.
27 ///
28 /// This struct maintains a *valid* status for level numbers, meaning that creating a new level, or
29 /// mutating an existing level, with the value smaller than `0` (before conversion to `u8`) or
30 /// larger than 125 results in an `Error`.
31 ///
32 /// <http://www.unicode.org/reports/tr9/#BD2>
33 #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
34 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
35 #[repr(transparent)]
36 pub struct Level(u8);
37 
38 pub const LTR_LEVEL: Level = Level(0);
39 pub const RTL_LEVEL: Level = Level(1);
40 
41 const MAX_DEPTH: u8 = 125;
42 /// During explicit level resolution, embedding level can go as high as `max_depth`.
43 pub const MAX_EXPLICIT_DEPTH: u8 = MAX_DEPTH;
44 /// During implicit level resolution, embedding level can go as high as `max_depth + 1`.
45 pub const MAX_IMPLICIT_DEPTH: u8 = MAX_DEPTH + 1;
46 
47 /// Errors that can occur on Level creation or mutation
48 #[derive(Debug, PartialEq)]
49 pub enum Error {
50     /// Out-of-range (invalid) embedding level number.
51     OutOfRangeNumber,
52 }
53 
54 impl Level {
55     /// New LTR level with smallest number value (0).
56     #[inline]
ltr() -> Level57     pub fn ltr() -> Level {
58         LTR_LEVEL
59     }
60 
61     /// New RTL level with smallest number value (1).
62     #[inline]
rtl() -> Level63     pub fn rtl() -> Level {
64         RTL_LEVEL
65     }
66 
67     /// Maximum depth of the directional status stack during implicit resolutions.
max_implicit_depth() -> u868     pub fn max_implicit_depth() -> u8 {
69         MAX_IMPLICIT_DEPTH
70     }
71 
72     /// Maximum depth of the directional status stack during explicit resolutions.
max_explicit_depth() -> u873     pub fn max_explicit_depth() -> u8 {
74         MAX_EXPLICIT_DEPTH
75     }
76 
77     // == Inquiries ==
78 
79     /// Create new level, fail if number is larger than `max_depth + 1`.
80     #[inline]
new(number: u8) -> Result<Level, Error>81     pub fn new(number: u8) -> Result<Level, Error> {
82         if number <= MAX_IMPLICIT_DEPTH {
83             Ok(Level(number))
84         } else {
85             Err(Error::OutOfRangeNumber)
86         }
87     }
88 
89     /// Create new level, fail if number is larger than `max_depth`.
90     #[inline]
new_explicit(number: u8) -> Result<Level, Error>91     pub fn new_explicit(number: u8) -> Result<Level, Error> {
92         if number <= MAX_EXPLICIT_DEPTH {
93             Ok(Level(number))
94         } else {
95             Err(Error::OutOfRangeNumber)
96         }
97     }
98 
99     // == Inquiries ==
100 
101     /// The level number.
102     #[inline]
number(&self) -> u8103     pub fn number(&self) -> u8 {
104         self.0
105     }
106 
107     /// If this level is left-to-right.
108     #[inline]
is_ltr(&self) -> bool109     pub fn is_ltr(&self) -> bool {
110         self.0 % 2 == 0
111     }
112 
113     /// If this level is right-to-left.
114     #[inline]
is_rtl(&self) -> bool115     pub fn is_rtl(&self) -> bool {
116         self.0 % 2 == 1
117     }
118 
119     // == Mutators ==
120 
121     /// Raise level by `amount`, fail if number is larger than `max_depth + 1`.
122     #[inline]
raise(&mut self, amount: u8) -> Result<(), Error>123     pub fn raise(&mut self, amount: u8) -> Result<(), Error> {
124         match self.0.checked_add(amount) {
125             Some(number) => {
126                 if number <= MAX_IMPLICIT_DEPTH {
127                     self.0 = number;
128                     Ok(())
129                 } else {
130                     Err(Error::OutOfRangeNumber)
131                 }
132             }
133             None => Err(Error::OutOfRangeNumber),
134         }
135     }
136 
137     /// Raise level by `amount`, fail if number is larger than `max_depth`.
138     #[inline]
raise_explicit(&mut self, amount: u8) -> Result<(), Error>139     pub fn raise_explicit(&mut self, amount: u8) -> Result<(), Error> {
140         match self.0.checked_add(amount) {
141             Some(number) => {
142                 if number <= MAX_EXPLICIT_DEPTH {
143                     self.0 = number;
144                     Ok(())
145                 } else {
146                     Err(Error::OutOfRangeNumber)
147                 }
148             }
149             None => Err(Error::OutOfRangeNumber),
150         }
151     }
152 
153     /// Lower level by `amount`, fail if number goes below zero.
154     #[inline]
lower(&mut self, amount: u8) -> Result<(), Error>155     pub fn lower(&mut self, amount: u8) -> Result<(), Error> {
156         match self.0.checked_sub(amount) {
157             Some(number) => {
158                 self.0 = number;
159                 Ok(())
160             }
161             None => Err(Error::OutOfRangeNumber),
162         }
163     }
164 
165     // == Helpers ==
166 
167     /// The next LTR (even) level greater than this, or fail if number is larger than `max_depth`.
168     #[inline]
new_explicit_next_ltr(&self) -> Result<Level, Error>169     pub fn new_explicit_next_ltr(&self) -> Result<Level, Error> {
170         Level::new_explicit((self.0 + 2) & !1)
171     }
172 
173     /// The next RTL (odd) level greater than this, or fail if number is larger than `max_depth`.
174     #[inline]
new_explicit_next_rtl(&self) -> Result<Level, Error>175     pub fn new_explicit_next_rtl(&self) -> Result<Level, Error> {
176         Level::new_explicit((self.0 + 1) | 1)
177     }
178 
179     /// The lowest RTL (odd) level greater than or equal to this, or fail if number is larger than
180     /// `max_depth + 1`.
181     #[inline]
new_lowest_ge_rtl(&self) -> Result<Level, Error>182     pub fn new_lowest_ge_rtl(&self) -> Result<Level, Error> {
183         Level::new(self.0 | 1)
184     }
185 
186     /// Generate a character type based on a level (as specified in steps X10 and N2).
187     #[inline]
bidi_class(&self) -> BidiClass188     pub fn bidi_class(&self) -> BidiClass {
189         if self.is_rtl() {
190             BidiClass::R
191         } else {
192             BidiClass::L
193         }
194     }
195 
vec(v: &[u8]) -> Vec<Level>196     pub fn vec(v: &[u8]) -> Vec<Level> {
197         v.iter().map(|&x| x.into()).collect()
198     }
199 
200     /// Converts a byte slice to a slice of Levels
201     ///
202     /// Does _not_ check if each level is within bounds (`<=` [`MAX_IMPLICIT_DEPTH`]),
203     /// which is not a requirement for safety but is a requirement for correctness of the algorithm.
from_slice_unchecked(v: &[u8]) -> &[Level]204     pub fn from_slice_unchecked(v: &[u8]) -> &[Level] {
205         debug_assert_eq!(core::mem::size_of::<u8>(), core::mem::size_of::<Level>());
206         unsafe {
207             // Safety: The two arrays are the same size and layout-compatible since
208             // Level is `repr(transparent)` over `u8`
209             slice::from_raw_parts(v as *const [u8] as *const u8 as *const Level, v.len())
210         }
211     }
212 }
213 
214 /// If levels has any RTL (odd) level
215 ///
216 /// This information is usually used to skip re-ordering of text when no RTL level is present
217 #[inline]
has_rtl(levels: &[Level]) -> bool218 pub fn has_rtl(levels: &[Level]) -> bool {
219     levels.iter().any(|&lvl| lvl.is_rtl())
220 }
221 
222 impl Into<u8> for Level {
223     /// Convert to the level number
224     #[inline]
into(self) -> u8225     fn into(self) -> u8 {
226         self.number()
227     }
228 }
229 
230 impl From<u8> for Level {
231     /// Create level by number
232     #[inline]
from(number: u8) -> Level233     fn from(number: u8) -> Level {
234         Level::new(number).expect("Level number error")
235     }
236 }
237 
238 /// Used for matching levels in conformance tests
239 impl<'a> PartialEq<&'a str> for Level {
240     #[inline]
eq(&self, s: &&'a str) -> bool241     fn eq(&self, s: &&'a str) -> bool {
242         *s == "x" || *s == self.0.to_string()
243     }
244 }
245 
246 /// Used for matching levels in conformance tests
247 impl<'a> PartialEq<String> for Level {
248     #[inline]
eq(&self, s: &String) -> bool249     fn eq(&self, s: &String) -> bool {
250         self == &s.as_str()
251     }
252 }
253 
254 #[cfg(test)]
255 mod tests {
256     use super::*;
257 
258     #[test]
test_new()259     fn test_new() {
260         assert_eq!(Level::new(0), Ok(Level(0)));
261         assert_eq!(Level::new(1), Ok(Level(1)));
262         assert_eq!(Level::new(10), Ok(Level(10)));
263         assert_eq!(Level::new(125), Ok(Level(125)));
264         assert_eq!(Level::new(126), Ok(Level(126)));
265         assert_eq!(Level::new(127), Err(Error::OutOfRangeNumber));
266         assert_eq!(Level::new(255), Err(Error::OutOfRangeNumber));
267     }
268 
269     #[test]
test_new_explicit()270     fn test_new_explicit() {
271         assert_eq!(Level::new_explicit(0), Ok(Level(0)));
272         assert_eq!(Level::new_explicit(1), Ok(Level(1)));
273         assert_eq!(Level::new_explicit(10), Ok(Level(10)));
274         assert_eq!(Level::new_explicit(125), Ok(Level(125)));
275         assert_eq!(Level::new_explicit(126), Err(Error::OutOfRangeNumber));
276         assert_eq!(Level::new_explicit(255), Err(Error::OutOfRangeNumber));
277     }
278 
279     #[test]
test_is_ltr()280     fn test_is_ltr() {
281         assert_eq!(Level(0).is_ltr(), true);
282         assert_eq!(Level(1).is_ltr(), false);
283         assert_eq!(Level(10).is_ltr(), true);
284         assert_eq!(Level(11).is_ltr(), false);
285         assert_eq!(Level(124).is_ltr(), true);
286         assert_eq!(Level(125).is_ltr(), false);
287     }
288 
289     #[test]
test_is_rtl()290     fn test_is_rtl() {
291         assert_eq!(Level(0).is_rtl(), false);
292         assert_eq!(Level(1).is_rtl(), true);
293         assert_eq!(Level(10).is_rtl(), false);
294         assert_eq!(Level(11).is_rtl(), true);
295         assert_eq!(Level(124).is_rtl(), false);
296         assert_eq!(Level(125).is_rtl(), true);
297     }
298 
299     #[test]
test_raise()300     fn test_raise() {
301         let mut level = Level::ltr();
302         assert_eq!(level.number(), 0);
303         assert!(level.raise(100).is_ok());
304         assert_eq!(level.number(), 100);
305         assert!(level.raise(26).is_ok());
306         assert_eq!(level.number(), 126);
307         assert!(level.raise(1).is_err()); // invalid!
308         assert!(level.raise(250).is_err()); // overflow!
309         assert_eq!(level.number(), 126);
310     }
311 
312     #[test]
test_raise_explicit()313     fn test_raise_explicit() {
314         let mut level = Level::ltr();
315         assert_eq!(level.number(), 0);
316         assert!(level.raise_explicit(100).is_ok());
317         assert_eq!(level.number(), 100);
318         assert!(level.raise_explicit(25).is_ok());
319         assert_eq!(level.number(), 125);
320         assert!(level.raise_explicit(1).is_err()); // invalid!
321         assert!(level.raise_explicit(250).is_err()); // overflow!
322         assert_eq!(level.number(), 125);
323     }
324 
325     #[test]
test_lower()326     fn test_lower() {
327         let mut level = Level::rtl();
328         assert_eq!(level.number(), 1);
329         assert!(level.lower(1).is_ok());
330         assert_eq!(level.number(), 0);
331         assert!(level.lower(1).is_err()); // underflow!
332         assert!(level.lower(250).is_err()); // underflow!
333         assert_eq!(level.number(), 0);
334     }
335 
336     #[test]
test_has_rtl()337     fn test_has_rtl() {
338         assert_eq!(has_rtl(&Level::vec(&[0, 0, 0])), false);
339         assert_eq!(has_rtl(&Level::vec(&[0, 1, 0])), true);
340         assert_eq!(has_rtl(&Level::vec(&[0, 2, 0])), false);
341         assert_eq!(has_rtl(&Level::vec(&[0, 125, 0])), true);
342         assert_eq!(has_rtl(&Level::vec(&[0, 126, 0])), false);
343     }
344 
345     #[test]
test_into()346     fn test_into() {
347         let level = Level::rtl();
348         let number: u8 = level.into();
349         assert_eq!(1u8, number);
350     }
351 
352     #[test]
test_vec()353     fn test_vec() {
354         assert_eq!(
355             Level::vec(&[0, 1, 125]),
356             vec![Level(0), Level(1), Level(125)]
357         );
358     }
359 
360     #[test]
test_str_eq()361     fn test_str_eq() {
362         assert_eq!(Level::vec(&[0, 1, 4, 125]), vec!["0", "1", "x", "125"]);
363         assert_ne!(Level::vec(&[0, 1, 4, 125]), vec!["0", "1", "5", "125"]);
364     }
365 
366     #[test]
test_string_eq()367     fn test_string_eq() {
368         assert_eq!(
369             Level::vec(&[0, 1, 4, 125]),
370             vec!["0".to_string(), "1".to_string(), "x".to_string(), "125".to_string()]
371         );
372     }
373 }
374 
375 #[cfg(all(feature = "serde", test))]
376 mod serde_tests {
377     use super::*;
378     use serde_test::{assert_tokens, Token};
379 
380     #[test]
test_statics()381     fn test_statics() {
382         assert_tokens(
383             &Level::ltr(),
384             &[Token::NewtypeStruct { name: "Level" }, Token::U8(0)],
385         );
386         assert_tokens(
387             &Level::rtl(),
388             &[Token::NewtypeStruct { name: "Level" }, Token::U8(1)],
389         );
390     }
391 
392     #[test]
test_new()393     fn test_new() {
394         let level = Level::new(42).unwrap();
395         assert_tokens(
396             &level,
397             &[Token::NewtypeStruct { name: "Level" }, Token::U8(42)],
398         );
399     }
400 }
401