• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::vec::Vec;
17 use core::convert::{From, Into};
18 use alloc::string::{String, ToString};
19 
20 use super::char_data::BidiClass;
21 
22 /// Embedding Level
23 ///
24 /// Embedding Levels are numbers between 0 and 126 (inclusive), where even values denote a
25 /// left-to-right (LTR) direction and odd values a right-to-left (RTL) direction.
26 ///
27 /// This struct maintains a *valid* status for level numbers, meaning that creating a new level, or
28 /// mutating an existing level, with the value smaller than `0` (before conversion to `u8`) or
29 /// larger than 125 results in an `Error`.
30 ///
31 /// <http://www.unicode.org/reports/tr9/#BD2>
32 #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
33 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34 pub struct Level(u8);
35 
36 pub const LTR_LEVEL: Level = Level(0);
37 pub const RTL_LEVEL: Level = Level(1);
38 
39 const MAX_DEPTH: u8 = 125;
40 /// During explicit level resolution, embedding level can go as high as `max_depth`.
41 pub const MAX_EXPLICIT_DEPTH: u8 = MAX_DEPTH;
42 /// During implicit level resolution, embedding level can go as high as `max_depth + 1`.
43 pub const MAX_IMPLICIT_DEPTH: u8 = MAX_DEPTH + 1;
44 
45 /// Errors that can occur on Level creation or mutation
46 #[derive(Debug, PartialEq)]
47 pub enum Error {
48     /// Out-of-range (invalid) embedding level number.
49     OutOfRangeNumber,
50 }
51 
52 impl Level {
53     /// New LTR level with smallest number value (0).
54     #[inline]
ltr() -> Level55     pub fn ltr() -> Level {
56         LTR_LEVEL
57     }
58 
59     /// New RTL level with smallest number value (1).
60     #[inline]
rtl() -> Level61     pub fn rtl() -> Level {
62         RTL_LEVEL
63     }
64 
65     /// Maximum depth of the directional status stack during implicit resolutions.
max_implicit_depth() -> u866     pub fn max_implicit_depth() -> u8 {
67         MAX_IMPLICIT_DEPTH
68     }
69 
70     /// Maximum depth of the directional status stack during explicit resolutions.
max_explicit_depth() -> u871     pub fn max_explicit_depth() -> u8 {
72         MAX_EXPLICIT_DEPTH
73     }
74 
75     // == Inquiries ==
76 
77     /// Create new level, fail if number is larger than `max_depth + 1`.
78     #[inline]
new(number: u8) -> Result<Level, Error>79     pub fn new(number: u8) -> Result<Level, Error> {
80         if number <= MAX_IMPLICIT_DEPTH {
81             Ok(Level(number))
82         } else {
83             Err(Error::OutOfRangeNumber)
84         }
85     }
86 
87     /// Create new level, fail if number is larger than `max_depth`.
88     #[inline]
new_explicit(number: u8) -> Result<Level, Error>89     pub fn new_explicit(number: u8) -> Result<Level, Error> {
90         if number <= MAX_EXPLICIT_DEPTH {
91             Ok(Level(number))
92         } else {
93             Err(Error::OutOfRangeNumber)
94         }
95     }
96 
97     // == Inquiries ==
98 
99     /// The level number.
100     #[inline]
number(&self) -> u8101     pub fn number(&self) -> u8 {
102         self.0
103     }
104 
105     /// If this level is left-to-right.
106     #[inline]
is_ltr(&self) -> bool107     pub fn is_ltr(&self) -> bool {
108         self.0 % 2 == 0
109     }
110 
111     /// If this level is right-to-left.
112     #[inline]
is_rtl(&self) -> bool113     pub fn is_rtl(&self) -> bool {
114         self.0 % 2 == 1
115     }
116 
117     // == Mutators ==
118 
119     /// Raise level by `amount`, fail if number is larger than `max_depth + 1`.
120     #[inline]
raise(&mut self, amount: u8) -> Result<(), Error>121     pub fn raise(&mut self, amount: u8) -> Result<(), Error> {
122         match self.0.checked_add(amount) {
123             Some(number) => {
124                 if number <= MAX_IMPLICIT_DEPTH {
125                     self.0 = number;
126                     Ok(())
127                 } else {
128                     Err(Error::OutOfRangeNumber)
129                 }
130             }
131             None => Err(Error::OutOfRangeNumber),
132         }
133     }
134 
135     /// Raise level by `amount`, fail if number is larger than `max_depth`.
136     #[inline]
raise_explicit(&mut self, amount: u8) -> Result<(), Error>137     pub fn raise_explicit(&mut self, amount: u8) -> Result<(), Error> {
138         match self.0.checked_add(amount) {
139             Some(number) => {
140                 if number <= MAX_EXPLICIT_DEPTH {
141                     self.0 = number;
142                     Ok(())
143                 } else {
144                     Err(Error::OutOfRangeNumber)
145                 }
146             }
147             None => Err(Error::OutOfRangeNumber),
148         }
149     }
150 
151     /// Lower level by `amount`, fail if number goes below zero.
152     #[inline]
lower(&mut self, amount: u8) -> Result<(), Error>153     pub fn lower(&mut self, amount: u8) -> Result<(), Error> {
154         match self.0.checked_sub(amount) {
155             Some(number) => {
156                 self.0 = number;
157                 Ok(())
158             }
159             None => Err(Error::OutOfRangeNumber),
160         }
161     }
162 
163     // == Helpers ==
164 
165     /// The next LTR (even) level greater than this, or fail if number is larger than `max_depth`.
166     #[inline]
new_explicit_next_ltr(&self) -> Result<Level, Error>167     pub fn new_explicit_next_ltr(&self) -> Result<Level, Error> {
168         Level::new_explicit((self.0 + 2) & !1)
169     }
170 
171     /// The next RTL (odd) level greater than this, or fail if number is larger than `max_depth`.
172     #[inline]
new_explicit_next_rtl(&self) -> Result<Level, Error>173     pub fn new_explicit_next_rtl(&self) -> Result<Level, Error> {
174         Level::new_explicit((self.0 + 1) | 1)
175     }
176 
177     /// The lowest RTL (odd) level greater than or equal to this, or fail if number is larger than
178     /// `max_depth + 1`.
179     #[inline]
new_lowest_ge_rtl(&self) -> Result<Level, Error>180     pub fn new_lowest_ge_rtl(&self) -> Result<Level, Error> {
181         Level::new(self.0 | 1)
182     }
183 
184     /// Generate a character type based on a level (as specified in steps X10 and N2).
185     #[inline]
bidi_class(&self) -> BidiClass186     pub fn bidi_class(&self) -> BidiClass {
187         if self.is_rtl() {
188             BidiClass::R
189         } else {
190             BidiClass::L
191         }
192     }
193 
vec(v: &[u8]) -> Vec<Level>194     pub fn vec(v: &[u8]) -> Vec<Level> {
195         v.iter().map(|&x| x.into()).collect()
196     }
197 }
198 
199 /// If levels has any RTL (odd) level
200 ///
201 /// This information is usually used to skip re-ordering of text when no RTL level is present
202 #[inline]
has_rtl(levels: &[Level]) -> bool203 pub fn has_rtl(levels: &[Level]) -> bool {
204     levels.iter().any(|&lvl| lvl.is_rtl())
205 }
206 
207 impl Into<u8> for Level {
208     /// Convert to the level number
209     #[inline]
into(self) -> u8210     fn into(self) -> u8 {
211         self.number()
212     }
213 }
214 
215 impl From<u8> for Level {
216     /// Create level by number
217     #[inline]
from(number: u8) -> Level218     fn from(number: u8) -> Level {
219         Level::new(number).expect("Level number error")
220     }
221 }
222 
223 /// Used for matching levels in conformance tests
224 impl<'a> PartialEq<&'a str> for Level {
225     #[inline]
eq(&self, s: &&'a str) -> bool226     fn eq(&self, s: &&'a str) -> bool {
227         *s == "x" || *s == self.0.to_string()
228     }
229 }
230 
231 /// Used for matching levels in conformance tests
232 impl<'a> PartialEq<String> for Level {
233     #[inline]
eq(&self, s: &String) -> bool234     fn eq(&self, s: &String) -> bool {
235         self == &s.as_str()
236     }
237 }
238 
239 #[cfg(test)]
240 mod tests {
241     use super::*;
242 
243     #[test]
test_new()244     fn test_new() {
245         assert_eq!(Level::new(0), Ok(Level(0)));
246         assert_eq!(Level::new(1), Ok(Level(1)));
247         assert_eq!(Level::new(10), Ok(Level(10)));
248         assert_eq!(Level::new(125), Ok(Level(125)));
249         assert_eq!(Level::new(126), Ok(Level(126)));
250         assert_eq!(Level::new(127), Err(Error::OutOfRangeNumber));
251         assert_eq!(Level::new(255), Err(Error::OutOfRangeNumber));
252     }
253 
254     #[test]
test_new_explicit()255     fn test_new_explicit() {
256         assert_eq!(Level::new_explicit(0), Ok(Level(0)));
257         assert_eq!(Level::new_explicit(1), Ok(Level(1)));
258         assert_eq!(Level::new_explicit(10), Ok(Level(10)));
259         assert_eq!(Level::new_explicit(125), Ok(Level(125)));
260         assert_eq!(Level::new_explicit(126), Err(Error::OutOfRangeNumber));
261         assert_eq!(Level::new_explicit(255), Err(Error::OutOfRangeNumber));
262     }
263 
264     #[test]
test_is_ltr()265     fn test_is_ltr() {
266         assert_eq!(Level(0).is_ltr(), true);
267         assert_eq!(Level(1).is_ltr(), false);
268         assert_eq!(Level(10).is_ltr(), true);
269         assert_eq!(Level(11).is_ltr(), false);
270         assert_eq!(Level(124).is_ltr(), true);
271         assert_eq!(Level(125).is_ltr(), false);
272     }
273 
274     #[test]
test_is_rtl()275     fn test_is_rtl() {
276         assert_eq!(Level(0).is_rtl(), false);
277         assert_eq!(Level(1).is_rtl(), true);
278         assert_eq!(Level(10).is_rtl(), false);
279         assert_eq!(Level(11).is_rtl(), true);
280         assert_eq!(Level(124).is_rtl(), false);
281         assert_eq!(Level(125).is_rtl(), true);
282     }
283 
284     #[test]
test_raise()285     fn test_raise() {
286         let mut level = Level::ltr();
287         assert_eq!(level.number(), 0);
288         assert!(level.raise(100).is_ok());
289         assert_eq!(level.number(), 100);
290         assert!(level.raise(26).is_ok());
291         assert_eq!(level.number(), 126);
292         assert!(level.raise(1).is_err()); // invalid!
293         assert!(level.raise(250).is_err()); // overflow!
294         assert_eq!(level.number(), 126);
295     }
296 
297     #[test]
test_raise_explicit()298     fn test_raise_explicit() {
299         let mut level = Level::ltr();
300         assert_eq!(level.number(), 0);
301         assert!(level.raise_explicit(100).is_ok());
302         assert_eq!(level.number(), 100);
303         assert!(level.raise_explicit(25).is_ok());
304         assert_eq!(level.number(), 125);
305         assert!(level.raise_explicit(1).is_err()); // invalid!
306         assert!(level.raise_explicit(250).is_err()); // overflow!
307         assert_eq!(level.number(), 125);
308     }
309 
310     #[test]
test_lower()311     fn test_lower() {
312         let mut level = Level::rtl();
313         assert_eq!(level.number(), 1);
314         assert!(level.lower(1).is_ok());
315         assert_eq!(level.number(), 0);
316         assert!(level.lower(1).is_err()); // underflow!
317         assert!(level.lower(250).is_err()); // underflow!
318         assert_eq!(level.number(), 0);
319     }
320 
321     #[test]
test_has_rtl()322     fn test_has_rtl() {
323         assert_eq!(has_rtl(&Level::vec(&[0, 0, 0])), false);
324         assert_eq!(has_rtl(&Level::vec(&[0, 1, 0])), true);
325         assert_eq!(has_rtl(&Level::vec(&[0, 2, 0])), false);
326         assert_eq!(has_rtl(&Level::vec(&[0, 125, 0])), true);
327         assert_eq!(has_rtl(&Level::vec(&[0, 126, 0])), false);
328     }
329 
330     #[test]
test_into()331     fn test_into() {
332         let level = Level::rtl();
333         let number: u8 = level.into();
334         assert_eq!(1u8, number);
335     }
336 
337     #[test]
test_vec()338     fn test_vec() {
339         assert_eq!(
340             Level::vec(&[0, 1, 125]),
341             vec![Level(0), Level(1), Level(125)]
342         );
343     }
344 
345     #[test]
test_str_eq()346     fn test_str_eq() {
347         assert_eq!(Level::vec(&[0, 1, 4, 125]), vec!["0", "1", "x", "125"]);
348         assert_ne!(Level::vec(&[0, 1, 4, 125]), vec!["0", "1", "5", "125"]);
349     }
350 
351     #[test]
test_string_eq()352     fn test_string_eq() {
353         assert_eq!(
354             Level::vec(&[0, 1, 4, 125]),
355             vec!["0".to_string(), "1".to_string(), "x".to_string(), "125".to_string()]
356         );
357     }
358 }
359 
360 #[cfg(all(feature = "serde", test))]
361 mod serde_tests {
362     use serde_test::{Token, assert_tokens};
363     use super::*;
364 
365     #[test]
test_statics()366     fn test_statics() {
367         assert_tokens(
368             &Level::ltr(),
369             &[Token::NewtypeStruct { name: "Level" }, Token::U8(0)],
370         );
371         assert_tokens(
372             &Level::rtl(),
373             &[Token::NewtypeStruct { name: "Level" }, Token::U8(1)],
374         );
375     }
376 
377     #[test]
test_new()378     fn test_new() {
379         let level = Level::new(42).unwrap();
380         assert_tokens(
381             &level,
382             &[Token::NewtypeStruct { name: "Level" }, Token::U8(42)],
383         );
384     }
385 }
386