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::string::{String, ToString}; |
17 | use alloc::vec::Vec; |
18 | use core::convert::{From, Into}; |
19 | use core::slice; |
20 | |
21 | use 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)] |
36 | pub struct Level(u8); |
37 | |
38 | pub const LTR_LEVEL: Level = Level(0); |
39 | pub const RTL_LEVEL: Level = Level(1); |
40 | |
41 | const MAX_DEPTH: u8 = 125; |
42 | /// During explicit level resolution, embedding level can go as high as `max_depth`. |
43 | pub const MAX_EXPLICIT_DEPTH: u8 = MAX_DEPTH; |
44 | /// During implicit level resolution, embedding level can go as high as `max_depth + 1`. |
45 | pub const MAX_IMPLICIT_DEPTH: u8 = MAX_DEPTH + 1; |
46 | |
47 | /// Errors that can occur on Level creation or mutation |
48 | #[derive (Debug, PartialEq)] |
49 | pub enum Error { |
50 | /// Out-of-range (invalid) embedding level number. |
51 | OutOfRangeNumber, |
52 | } |
53 | |
54 | impl 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 ] |
218 | pub fn has_rtl(levels: &[Level]) -> bool { |
219 | levels.iter().any(|&lvl: Level| lvl.is_rtl()) |
220 | } |
221 | |
222 | impl Into<u8> for Level { |
223 | /// Convert to the level number |
224 | #[inline ] |
225 | fn into(self) -> u8 { |
226 | self.number() |
227 | } |
228 | } |
229 | |
230 | impl 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 |
239 | impl<'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 |
247 | impl<'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)] |
255 | mod 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))] |
376 | mod 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 | |