1 // Copyright 2015 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 //! Accessor for `Bidi_Class` property from Unicode Character Database (UCD)
11
12 mod tables;
13
14 pub use self::tables::{BidiClass, UNICODE_VERSION};
15
16 use std::cmp::Ordering::{Equal, Less, Greater};
17 use std::char;
18
19 use self::tables::bidi_class_table;
20 use BidiClass::*;
21
22 /// Find the `BidiClass` of a single char.
bidi_class(c: char) -> BidiClass23 pub fn bidi_class(c: char) -> BidiClass {
24 bsearch_range_value_table(c, bidi_class_table)
25 }
26
is_rtl(bidi_class: BidiClass) -> bool27 pub fn is_rtl(bidi_class: BidiClass) -> bool {
28 match bidi_class {
29 RLE | RLO | RLI => true,
30 _ => false,
31 }
32 }
33
bsearch_range_value_table(c: char, r: &'static [(char, char, BidiClass)]) -> BidiClass34 fn bsearch_range_value_table(c: char, r: &'static [(char, char, BidiClass)]) -> BidiClass {
35 match r.binary_search_by(|&(lo, hi, _)| if lo <= c && c <= hi {
36 Equal
37 } else if hi < c {
38 Less
39 } else {
40 Greater
41 }) {
42 Ok(idx) => {
43 let (_, _, cat) = r[idx];
44 cat
45 }
46 // UCD/extracted/DerivedBidiClass.txt: "All code points not explicitly listed
47 // for Bidi_Class have the value Left_To_Right (L)."
48 Err(_) => L,
49 }
50 }
51
52 #[cfg(test)]
53 mod tests {
54 use super::*;
55
56 #[test]
test_ascii()57 fn test_ascii() {
58 assert_eq!(bidi_class('\u{0000}'), BN);
59 assert_eq!(bidi_class('\u{0040}'), ON);
60 assert_eq!(bidi_class('\u{0041}'), L);
61 assert_eq!(bidi_class('\u{0062}'), L);
62 assert_eq!(bidi_class('\u{007F}'), BN);
63 }
64
65 #[test]
test_bmp()66 fn test_bmp() {
67 // Hebrew
68 assert_eq!(bidi_class('\u{0590}'), R);
69 assert_eq!(bidi_class('\u{05D0}'), R);
70 assert_eq!(bidi_class('\u{05D1}'), R);
71 assert_eq!(bidi_class('\u{05FF}'), R);
72
73 // Arabic
74 assert_eq!(bidi_class('\u{0600}'), AN);
75 assert_eq!(bidi_class('\u{0627}'), AL);
76 assert_eq!(bidi_class('\u{07BF}'), AL);
77
78 // Default R + Arabic Extras
79 assert_eq!(bidi_class('\u{07C0}'), R);
80 assert_eq!(bidi_class('\u{085F}'), R);
81 assert_eq!(bidi_class('\u{0860}'), AL);
82 assert_eq!(bidi_class('\u{0870}'), R);
83 assert_eq!(bidi_class('\u{089F}'), R);
84 assert_eq!(bidi_class('\u{08A0}'), AL);
85 assert_eq!(bidi_class('\u{089F}'), R);
86 assert_eq!(bidi_class('\u{08FF}'), NSM);
87
88 // Default ET
89 assert_eq!(bidi_class('\u{20A0}'), ET);
90 assert_eq!(bidi_class('\u{20CF}'), ET);
91
92 // Arabic Presentation Forms
93 assert_eq!(bidi_class('\u{FB1D}'), R);
94 assert_eq!(bidi_class('\u{FB4F}'), R);
95 assert_eq!(bidi_class('\u{FB50}'), AL);
96 assert_eq!(bidi_class('\u{FDCF}'), AL);
97 assert_eq!(bidi_class('\u{FDF0}'), AL);
98 assert_eq!(bidi_class('\u{FDFF}'), AL);
99 assert_eq!(bidi_class('\u{FE70}'), AL);
100 assert_eq!(bidi_class('\u{FEFE}'), AL);
101 assert_eq!(bidi_class('\u{FEFF}'), BN);
102
103 // noncharacters
104 assert_eq!(bidi_class('\u{FDD0}'), L);
105 assert_eq!(bidi_class('\u{FDD1}'), L);
106 assert_eq!(bidi_class('\u{FDEE}'), L);
107 assert_eq!(bidi_class('\u{FDEF}'), L);
108 assert_eq!(bidi_class('\u{FFFE}'), L);
109 assert_eq!(bidi_class('\u{FFFF}'), L);
110 }
111
112 #[test]
test_smp()113 fn test_smp() {
114 // Default AL + R
115 assert_eq!(bidi_class('\u{10800}'), R);
116 assert_eq!(bidi_class('\u{10FFF}'), R);
117 assert_eq!(bidi_class('\u{1E800}'), R);
118 assert_eq!(bidi_class('\u{1EDFF}'), R);
119 assert_eq!(bidi_class('\u{1EE00}'), AL);
120 assert_eq!(bidi_class('\u{1EEFF}'), AL);
121 assert_eq!(bidi_class('\u{1EF00}'), R);
122 assert_eq!(bidi_class('\u{1EFFF}'), R);
123 }
124
125 #[test]
test_unassigned_planes()126 fn test_unassigned_planes() {
127 assert_eq!(bidi_class('\u{30000}'), L);
128 assert_eq!(bidi_class('\u{40000}'), L);
129 assert_eq!(bidi_class('\u{50000}'), L);
130 assert_eq!(bidi_class('\u{60000}'), L);
131 assert_eq!(bidi_class('\u{70000}'), L);
132 assert_eq!(bidi_class('\u{80000}'), L);
133 assert_eq!(bidi_class('\u{90000}'), L);
134 assert_eq!(bidi_class('\u{a0000}'), L);
135 }
136 }
137