unicode_bidi/
level.rs

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