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