unic_bidi/
level.rs

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