1 | /*! |
2 | |
3 | This library implements |
4 | [Unicode Bidi Mirroring](https://unicode.org/reports/tr44/#BidiMirroring.txt) property detection. |
5 | |
6 | ```rust |
7 | use unicode_bidi_mirroring::*; |
8 | |
9 | assert_eq!(get_mirrored('A' ), None); |
10 | assert_eq!(get_mirrored(' \u{2039}' ), Some(' \u{203A}' )); |
11 | assert_eq!(get_mirrored(' \u{203A}' ), Some(' \u{2039}' )); |
12 | |
13 | assert_eq!(is_mirroring('A' ), false); |
14 | assert_eq!(is_mirroring(' \u{29C4}' ), true); |
15 | assert_eq!(is_mirroring(' \u{22FF}' ), true); |
16 | ``` |
17 | |
18 | */ |
19 | |
20 | #![doc (html_root_url = "https://docs.rs/unicode-bidi-mirroring/0.1.0" )] |
21 | #![no_std ] |
22 | #![forbid (unsafe_code)] |
23 | |
24 | /// The Unicode version. |
25 | pub const UNICODE_VERSION: (u8, u8, u8) = (13, 0, 0); |
26 | |
27 | const PAIRS: &[(char, char)] = &[ |
28 | (' \u{0028}' , ' \u{0029}' ), |
29 | (' \u{003C}' , ' \u{003E}' ), |
30 | (' \u{005B}' , ' \u{005D}' ), |
31 | (' \u{007B}' , ' \u{007D}' ), |
32 | (' \u{00AB}' , ' \u{00BB}' ), |
33 | (' \u{0F3A}' , ' \u{0F3B}' ), |
34 | (' \u{0F3C}' , ' \u{0F3D}' ), |
35 | (' \u{169B}' , ' \u{169C}' ), |
36 | (' \u{2039}' , ' \u{203A}' ), |
37 | (' \u{2045}' , ' \u{2046}' ), |
38 | (' \u{207D}' , ' \u{207E}' ), |
39 | (' \u{208D}' , ' \u{208E}' ), |
40 | (' \u{2208}' , ' \u{220B}' ), |
41 | (' \u{2209}' , ' \u{220C}' ), |
42 | (' \u{220A}' , ' \u{220D}' ), |
43 | (' \u{2215}' , ' \u{29F5}' ), |
44 | (' \u{221F}' , ' \u{2BFE}' ), |
45 | (' \u{2220}' , ' \u{29A3}' ), |
46 | (' \u{2221}' , ' \u{299B}' ), |
47 | (' \u{2222}' , ' \u{29A0}' ), |
48 | (' \u{2224}' , ' \u{2AEE}' ), |
49 | (' \u{223C}' , ' \u{223D}' ), |
50 | (' \u{2243}' , ' \u{22CD}' ), |
51 | (' \u{2245}' , ' \u{224C}' ), |
52 | (' \u{2252}' , ' \u{2253}' ), |
53 | (' \u{2254}' , ' \u{2255}' ), |
54 | (' \u{2264}' , ' \u{2265}' ), |
55 | (' \u{2266}' , ' \u{2267}' ), |
56 | (' \u{2268}' , ' \u{2269}' ), |
57 | (' \u{226A}' , ' \u{226B}' ), |
58 | (' \u{226E}' , ' \u{226F}' ), |
59 | (' \u{2270}' , ' \u{2271}' ), |
60 | (' \u{2272}' , ' \u{2273}' ), |
61 | (' \u{2274}' , ' \u{2275}' ), |
62 | (' \u{2276}' , ' \u{2277}' ), |
63 | (' \u{2278}' , ' \u{2279}' ), |
64 | (' \u{227A}' , ' \u{227B}' ), |
65 | (' \u{227C}' , ' \u{227D}' ), |
66 | (' \u{227E}' , ' \u{227F}' ), |
67 | (' \u{2280}' , ' \u{2281}' ), |
68 | (' \u{2282}' , ' \u{2283}' ), |
69 | (' \u{2284}' , ' \u{2285}' ), |
70 | (' \u{2286}' , ' \u{2287}' ), |
71 | (' \u{2288}' , ' \u{2289}' ), |
72 | (' \u{228A}' , ' \u{228B}' ), |
73 | (' \u{228F}' , ' \u{2290}' ), |
74 | (' \u{2291}' , ' \u{2292}' ), |
75 | (' \u{2298}' , ' \u{29B8}' ), |
76 | (' \u{22A2}' , ' \u{22A3}' ), |
77 | (' \u{22A6}' , ' \u{2ADE}' ), |
78 | (' \u{22A8}' , ' \u{2AE4}' ), |
79 | (' \u{22A9}' , ' \u{2AE3}' ), |
80 | (' \u{22AB}' , ' \u{2AE5}' ), |
81 | (' \u{22B0}' , ' \u{22B1}' ), |
82 | (' \u{22B2}' , ' \u{22B3}' ), |
83 | (' \u{22B4}' , ' \u{22B5}' ), |
84 | (' \u{22B6}' , ' \u{22B7}' ), |
85 | (' \u{22B8}' , ' \u{27DC}' ), |
86 | (' \u{22C9}' , ' \u{22CA}' ), |
87 | (' \u{22CB}' , ' \u{22CC}' ), |
88 | (' \u{22D0}' , ' \u{22D1}' ), |
89 | (' \u{22D6}' , ' \u{22D7}' ), |
90 | (' \u{22D8}' , ' \u{22D9}' ), |
91 | (' \u{22DA}' , ' \u{22DB}' ), |
92 | (' \u{22DC}' , ' \u{22DD}' ), |
93 | (' \u{22DE}' , ' \u{22DF}' ), |
94 | (' \u{22E0}' , ' \u{22E1}' ), |
95 | (' \u{22E2}' , ' \u{22E3}' ), |
96 | (' \u{22E4}' , ' \u{22E5}' ), |
97 | (' \u{22E6}' , ' \u{22E7}' ), |
98 | (' \u{22E8}' , ' \u{22E9}' ), |
99 | (' \u{22EA}' , ' \u{22EB}' ), |
100 | (' \u{22EC}' , ' \u{22ED}' ), |
101 | (' \u{22F0}' , ' \u{22F1}' ), |
102 | (' \u{22F2}' , ' \u{22FA}' ), |
103 | (' \u{22F3}' , ' \u{22FB}' ), |
104 | (' \u{22F4}' , ' \u{22FC}' ), |
105 | (' \u{22F6}' , ' \u{22FD}' ), |
106 | (' \u{22F7}' , ' \u{22FE}' ), |
107 | (' \u{2308}' , ' \u{2309}' ), |
108 | (' \u{230A}' , ' \u{230B}' ), |
109 | (' \u{2329}' , ' \u{232A}' ), |
110 | (' \u{2768}' , ' \u{2769}' ), |
111 | (' \u{276A}' , ' \u{276B}' ), |
112 | (' \u{276C}' , ' \u{276D}' ), |
113 | (' \u{276E}' , ' \u{276F}' ), |
114 | (' \u{2770}' , ' \u{2771}' ), |
115 | (' \u{2772}' , ' \u{2773}' ), |
116 | (' \u{2774}' , ' \u{2775}' ), |
117 | (' \u{27C3}' , ' \u{27C4}' ), |
118 | (' \u{27C5}' , ' \u{27C6}' ), |
119 | (' \u{27C8}' , ' \u{27C9}' ), |
120 | (' \u{27CB}' , ' \u{27CD}' ), |
121 | (' \u{27D5}' , ' \u{27D6}' ), |
122 | (' \u{27DD}' , ' \u{27DE}' ), |
123 | (' \u{27E2}' , ' \u{27E3}' ), |
124 | (' \u{27E4}' , ' \u{27E5}' ), |
125 | (' \u{27E6}' , ' \u{27E7}' ), |
126 | (' \u{27E8}' , ' \u{27E9}' ), |
127 | (' \u{27EA}' , ' \u{27EB}' ), |
128 | (' \u{27EC}' , ' \u{27ED}' ), |
129 | (' \u{27EE}' , ' \u{27EF}' ), |
130 | (' \u{2983}' , ' \u{2984}' ), |
131 | (' \u{2985}' , ' \u{2986}' ), |
132 | (' \u{2987}' , ' \u{2988}' ), |
133 | (' \u{2989}' , ' \u{298A}' ), |
134 | (' \u{298B}' , ' \u{298C}' ), |
135 | (' \u{298D}' , ' \u{2990}' ), |
136 | (' \u{298E}' , ' \u{298F}' ), |
137 | (' \u{2991}' , ' \u{2992}' ), |
138 | (' \u{2993}' , ' \u{2994}' ), |
139 | (' \u{2995}' , ' \u{2996}' ), |
140 | (' \u{2997}' , ' \u{2998}' ), |
141 | (' \u{29A4}' , ' \u{29A5}' ), |
142 | (' \u{29A8}' , ' \u{29A9}' ), |
143 | (' \u{29AA}' , ' \u{29AB}' ), |
144 | (' \u{29AC}' , ' \u{29AD}' ), |
145 | (' \u{29AE}' , ' \u{29AF}' ), |
146 | (' \u{29C0}' , ' \u{29C1}' ), |
147 | (' \u{29C4}' , ' \u{29C5}' ), |
148 | (' \u{29CF}' , ' \u{29D0}' ), |
149 | (' \u{29D1}' , ' \u{29D2}' ), |
150 | (' \u{29D4}' , ' \u{29D5}' ), |
151 | (' \u{29D8}' , ' \u{29D9}' ), |
152 | (' \u{29DA}' , ' \u{29DB}' ), |
153 | (' \u{29E8}' , ' \u{29E9}' ), |
154 | (' \u{29F8}' , ' \u{29F9}' ), |
155 | (' \u{29FC}' , ' \u{29FD}' ), |
156 | (' \u{2A2B}' , ' \u{2A2C}' ), |
157 | (' \u{2A2D}' , ' \u{2A2E}' ), |
158 | (' \u{2A34}' , ' \u{2A35}' ), |
159 | (' \u{2A3C}' , ' \u{2A3D}' ), |
160 | (' \u{2A64}' , ' \u{2A65}' ), |
161 | (' \u{2A79}' , ' \u{2A7A}' ), |
162 | (' \u{2A7B}' , ' \u{2A7C}' ), |
163 | (' \u{2A7D}' , ' \u{2A7E}' ), |
164 | (' \u{2A7F}' , ' \u{2A80}' ), |
165 | (' \u{2A81}' , ' \u{2A82}' ), |
166 | (' \u{2A83}' , ' \u{2A84}' ), |
167 | (' \u{2A85}' , ' \u{2A86}' ), |
168 | (' \u{2A87}' , ' \u{2A88}' ), |
169 | (' \u{2A89}' , ' \u{2A8A}' ), |
170 | (' \u{2A8B}' , ' \u{2A8C}' ), |
171 | (' \u{2A8D}' , ' \u{2A8E}' ), |
172 | (' \u{2A8F}' , ' \u{2A90}' ), |
173 | (' \u{2A91}' , ' \u{2A92}' ), |
174 | (' \u{2A93}' , ' \u{2A94}' ), |
175 | (' \u{2A95}' , ' \u{2A96}' ), |
176 | (' \u{2A97}' , ' \u{2A98}' ), |
177 | (' \u{2A99}' , ' \u{2A9A}' ), |
178 | (' \u{2A9B}' , ' \u{2A9C}' ), |
179 | (' \u{2A9D}' , ' \u{2A9E}' ), |
180 | (' \u{2A9F}' , ' \u{2AA0}' ), |
181 | (' \u{2AA1}' , ' \u{2AA2}' ), |
182 | (' \u{2AA6}' , ' \u{2AA7}' ), |
183 | (' \u{2AA8}' , ' \u{2AA9}' ), |
184 | (' \u{2AAA}' , ' \u{2AAB}' ), |
185 | (' \u{2AAC}' , ' \u{2AAD}' ), |
186 | (' \u{2AAF}' , ' \u{2AB0}' ), |
187 | (' \u{2AB1}' , ' \u{2AB2}' ), |
188 | (' \u{2AB3}' , ' \u{2AB4}' ), |
189 | (' \u{2AB5}' , ' \u{2AB6}' ), |
190 | (' \u{2AB7}' , ' \u{2AB8}' ), |
191 | (' \u{2AB9}' , ' \u{2ABA}' ), |
192 | (' \u{2ABB}' , ' \u{2ABC}' ), |
193 | (' \u{2ABD}' , ' \u{2ABE}' ), |
194 | (' \u{2ABF}' , ' \u{2AC0}' ), |
195 | (' \u{2AC1}' , ' \u{2AC2}' ), |
196 | (' \u{2AC3}' , ' \u{2AC4}' ), |
197 | (' \u{2AC5}' , ' \u{2AC6}' ), |
198 | (' \u{2AC7}' , ' \u{2AC8}' ), |
199 | (' \u{2AC9}' , ' \u{2ACA}' ), |
200 | (' \u{2ACB}' , ' \u{2ACC}' ), |
201 | (' \u{2ACD}' , ' \u{2ACE}' ), |
202 | (' \u{2ACF}' , ' \u{2AD0}' ), |
203 | (' \u{2AD1}' , ' \u{2AD2}' ), |
204 | (' \u{2AD3}' , ' \u{2AD4}' ), |
205 | (' \u{2AD5}' , ' \u{2AD6}' ), |
206 | (' \u{2AEC}' , ' \u{2AED}' ), |
207 | (' \u{2AF7}' , ' \u{2AF8}' ), |
208 | (' \u{2AF9}' , ' \u{2AFA}' ), |
209 | (' \u{2E02}' , ' \u{2E03}' ), |
210 | (' \u{2E04}' , ' \u{2E05}' ), |
211 | (' \u{2E09}' , ' \u{2E0A}' ), |
212 | (' \u{2E0C}' , ' \u{2E0D}' ), |
213 | (' \u{2E1C}' , ' \u{2E1D}' ), |
214 | (' \u{2E20}' , ' \u{2E21}' ), |
215 | (' \u{2E22}' , ' \u{2E23}' ), |
216 | (' \u{2E24}' , ' \u{2E25}' ), |
217 | (' \u{2E26}' , ' \u{2E27}' ), |
218 | (' \u{2E28}' , ' \u{2E29}' ), |
219 | (' \u{3008}' , ' \u{3009}' ), |
220 | (' \u{300A}' , ' \u{300B}' ), |
221 | (' \u{300C}' , ' \u{300D}' ), |
222 | (' \u{300E}' , ' \u{300F}' ), |
223 | (' \u{3010}' , ' \u{3011}' ), |
224 | (' \u{3014}' , ' \u{3015}' ), |
225 | (' \u{3016}' , ' \u{3017}' ), |
226 | (' \u{3018}' , ' \u{3019}' ), |
227 | (' \u{301A}' , ' \u{301B}' ), |
228 | (' \u{FE59}' , ' \u{FE5A}' ), |
229 | (' \u{FE5B}' , ' \u{FE5C}' ), |
230 | (' \u{FE5D}' , ' \u{FE5E}' ), |
231 | (' \u{FE64}' , ' \u{FE65}' ), |
232 | (' \u{FF08}' , ' \u{FF09}' ), |
233 | (' \u{FF1C}' , ' \u{FF1E}' ), |
234 | (' \u{FF3B}' , ' \u{FF3D}' ), |
235 | (' \u{FF5B}' , ' \u{FF5D}' ), |
236 | (' \u{FF5F}' , ' \u{FF60}' ), |
237 | (' \u{FF62}' , ' \u{FF63}' ), |
238 | ]; |
239 | |
240 | const OTHER: &[char] = &[ |
241 | ' \u{2140}' , |
242 | ' \u{2201}' , |
243 | ' \u{2202}' , |
244 | ' \u{2203}' , |
245 | ' \u{2204}' , |
246 | ' \u{2211}' , |
247 | ' \u{2216}' , |
248 | ' \u{221A}' , |
249 | ' \u{221B}' , |
250 | ' \u{221C}' , |
251 | ' \u{221D}' , |
252 | ' \u{2226}' , |
253 | ' \u{222B}' , |
254 | ' \u{222C}' , |
255 | ' \u{222D}' , |
256 | ' \u{222E}' , |
257 | ' \u{222F}' , |
258 | ' \u{2230}' , |
259 | ' \u{2231}' , |
260 | ' \u{2232}' , |
261 | ' \u{2233}' , |
262 | ' \u{2239}' , |
263 | ' \u{223B}' , |
264 | ' \u{223E}' , |
265 | ' \u{223F}' , |
266 | ' \u{2240}' , |
267 | ' \u{2241}' , |
268 | ' \u{2242}' , |
269 | ' \u{2244}' , |
270 | ' \u{2246}' , |
271 | ' \u{2247}' , |
272 | ' \u{2248}' , |
273 | ' \u{2249}' , |
274 | ' \u{224A}' , |
275 | ' \u{224B}' , |
276 | ' \u{225F}' , |
277 | ' \u{2260}' , |
278 | ' \u{2262}' , |
279 | ' \u{228C}' , |
280 | ' \u{22A7}' , |
281 | ' \u{22AA}' , |
282 | ' \u{22AC}' , |
283 | ' \u{22AD}' , |
284 | ' \u{22AE}' , |
285 | ' \u{22AF}' , |
286 | ' \u{22BE}' , |
287 | ' \u{22BF}' , |
288 | ' \u{22F5}' , |
289 | ' \u{22F8}' , |
290 | ' \u{22F9}' , |
291 | ' \u{22FF}' , |
292 | ' \u{2320}' , |
293 | ' \u{2321}' , |
294 | ' \u{27C0}' , |
295 | ' \u{27CC}' , |
296 | ' \u{27D3}' , |
297 | ' \u{27D4}' , |
298 | ' \u{299C}' , |
299 | ' \u{299D}' , |
300 | ' \u{299E}' , |
301 | ' \u{299F}' , |
302 | ' \u{29A2}' , |
303 | ' \u{29A6}' , |
304 | ' \u{29A7}' , |
305 | ' \u{29C2}' , |
306 | ' \u{29C3}' , |
307 | ' \u{29C9}' , |
308 | ' \u{29CE}' , |
309 | ' \u{29DC}' , |
310 | ' \u{29E1}' , |
311 | ' \u{29E3}' , |
312 | ' \u{29E4}' , |
313 | ' \u{29E5}' , |
314 | ' \u{29F4}' , |
315 | ' \u{29F6}' , |
316 | ' \u{29F7}' , |
317 | ' \u{2A0A}' , |
318 | ' \u{2A0B}' , |
319 | ' \u{2A0C}' , |
320 | ' \u{2A0D}' , |
321 | ' \u{2A0E}' , |
322 | ' \u{2A0F}' , |
323 | ' \u{2A10}' , |
324 | ' \u{2A11}' , |
325 | ' \u{2A12}' , |
326 | ' \u{2A13}' , |
327 | ' \u{2A14}' , |
328 | ' \u{2A15}' , |
329 | ' \u{2A16}' , |
330 | ' \u{2A17}' , |
331 | ' \u{2A18}' , |
332 | ' \u{2A19}' , |
333 | ' \u{2A1A}' , |
334 | ' \u{2A1B}' , |
335 | ' \u{2A1C}' , |
336 | ' \u{2A1E}' , |
337 | ' \u{2A1F}' , |
338 | ' \u{2A20}' , |
339 | ' \u{2A21}' , |
340 | ' \u{2A24}' , |
341 | ' \u{2A26}' , |
342 | ' \u{2A29}' , |
343 | ' \u{2A3E}' , |
344 | ' \u{2A57}' , |
345 | ' \u{2A58}' , |
346 | ' \u{2A6A}' , |
347 | ' \u{2A6B}' , |
348 | ' \u{2A6C}' , |
349 | ' \u{2A6D}' , |
350 | ' \u{2A6F}' , |
351 | ' \u{2A70}' , |
352 | ' \u{2A73}' , |
353 | ' \u{2A74}' , |
354 | ' \u{2AA3}' , |
355 | ' \u{2ADC}' , |
356 | ' \u{2AE2}' , |
357 | ' \u{2AE6}' , |
358 | ' \u{2AF3}' , |
359 | ' \u{2AFB}' , |
360 | ' \u{2AFD}' , |
361 | ' \u{1D6DB}' , |
362 | ' \u{1D715}' , |
363 | ' \u{1D74F}' , |
364 | ' \u{1D789}' , |
365 | ' \u{1D7C3}' , |
366 | ]; |
367 | |
368 | /// Returns a bidi mirrored character. |
369 | /// |
370 | /// Based on <https://www.unicode.org/Public/UNIDATA/BidiMirroring.txt>. |
371 | pub fn get_mirrored(c: char) -> Option<char> { |
372 | if let Ok(idx: usize) = PAIRS.binary_search_by(|v: &(char, char)| v.0.cmp(&c)) { |
373 | return Some(PAIRS[idx].1); |
374 | } |
375 | |
376 | if let Ok(idx: usize) = PAIRS.binary_search_by(|v: &(char, char)| v.1.cmp(&c)) { |
377 | return Some(PAIRS[idx].0); |
378 | } |
379 | |
380 | None |
381 | } |
382 | |
383 | /// Checks that character is bidi mirrored. |
384 | /// |
385 | /// Based on <https://www.unicode.org/Public/UNIDATA/BidiMirroring.txt>. |
386 | pub fn is_mirroring(c: char) -> bool { |
387 | PAIRS.binary_search_by(|v: &(char, char)| v.0.cmp(&c)).is_ok() || |
388 | PAIRS.binary_search_by(|v: &(char, char)| v.1.cmp(&c)).is_ok() || |
389 | OTHER.binary_search_by(|v: &char| v.cmp(&c)).is_ok() |
390 | } |
391 | |