| 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 | |