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