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::{ |
17 | string::{String, ToString}, |
18 | vec::Vec, |
19 | }; |
20 | use core::slice; |
21 | |
22 | use 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)] |
37 | pub struct Level(u8); |
38 | |
39 | pub const LTR_LEVEL: Level = Level(0); |
40 | pub const RTL_LEVEL: Level = Level(1); |
41 | |
42 | const MAX_DEPTH: u8 = 125; |
43 | /// During explicit level resolution, embedding level can go as high as `max_depth`. |
44 | pub const MAX_EXPLICIT_DEPTH: u8 = MAX_DEPTH; |
45 | /// During implicit level resolution, embedding level can go as high as `max_depth + 1`. |
46 | pub const MAX_IMPLICIT_DEPTH: u8 = MAX_DEPTH + 1; |
47 | |
48 | /// Errors that can occur on Level creation or mutation |
49 | #[derive (Debug, PartialEq)] |
50 | pub enum Error { |
51 | /// Out-of-range (invalid) embedding level number. |
52 | OutOfRangeNumber, |
53 | } |
54 | |
55 | impl 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 ] |
219 | pub fn has_rtl(levels: &[Level]) -> bool { |
220 | levels.iter().any(|&lvl: Level| lvl.is_rtl()) |
221 | } |
222 | |
223 | impl From<Level> for u8 { |
224 | /// Convert to the level number |
225 | #[inline ] |
226 | fn from(val: Level) -> Self { |
227 | val.number() |
228 | } |
229 | } |
230 | |
231 | impl From<u8> for Level { |
232 | /// Create level by number |
233 | #[inline ] |
234 | fn from(number: u8) -> Level { |
235 | Level::new(number).expect(msg:"Level number error" ) |
236 | } |
237 | } |
238 | |
239 | /// Used for matching levels in conformance tests |
240 | impl<'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 |
248 | impl PartialEq<String> for Level { |
249 | #[inline ] |
250 | fn eq(&self, s: &String) -> bool { |
251 | self == &s.as_str() |
252 | } |
253 | } |
254 | |
255 | #[cfg (test)] |
256 | mod 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))] |
377 | mod 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 | } |
402 | |