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