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