/*! This library implements [Unicode Bidi Mirroring](https://unicode.org/reports/tr44/#BidiMirroring.txt) property detection. ```rust use unicode_bidi_mirroring::*; assert_eq!(get_mirrored('A'), None); assert_eq!(get_mirrored('\u{2039}'), Some('\u{203A}')); assert_eq!(get_mirrored('\u{203A}'), Some('\u{2039}')); assert_eq!(is_mirroring('A'), false); assert_eq!(is_mirroring('\u{29C4}'), true); assert_eq!(is_mirroring('\u{22FF}'), true); ``` */ #![no_std] #![forbid(unsafe_code)] /// The Unicode version. pub const UNICODE_VERSION: (u8, u8, u8) = (14, 0, 0); const PAIRS: &[(char, char)] = &[ ('\u{0028}', '\u{0029}'), ('\u{003C}', '\u{003E}'), ('\u{005B}', '\u{005D}'), ('\u{007B}', '\u{007D}'), ('\u{00AB}', '\u{00BB}'), ('\u{0F3A}', '\u{0F3B}'), ('\u{0F3C}', '\u{0F3D}'), ('\u{169B}', '\u{169C}'), ('\u{2039}', '\u{203A}'), ('\u{2045}', '\u{2046}'), ('\u{207D}', '\u{207E}'), ('\u{208D}', '\u{208E}'), ('\u{2208}', '\u{220B}'), ('\u{2209}', '\u{220C}'), ('\u{220A}', '\u{220D}'), ('\u{2215}', '\u{29F5}'), ('\u{221F}', '\u{2BFE}'), ('\u{2220}', '\u{29A3}'), ('\u{2221}', '\u{299B}'), ('\u{2222}', '\u{29A0}'), ('\u{2224}', '\u{2AEE}'), ('\u{223C}', '\u{223D}'), ('\u{2243}', '\u{22CD}'), ('\u{2245}', '\u{224C}'), ('\u{2252}', '\u{2253}'), ('\u{2254}', '\u{2255}'), ('\u{2264}', '\u{2265}'), ('\u{2266}', '\u{2267}'), ('\u{2268}', '\u{2269}'), ('\u{226A}', '\u{226B}'), ('\u{226E}', '\u{226F}'), ('\u{2270}', '\u{2271}'), ('\u{2272}', '\u{2273}'), ('\u{2274}', '\u{2275}'), ('\u{2276}', '\u{2277}'), ('\u{2278}', '\u{2279}'), ('\u{227A}', '\u{227B}'), ('\u{227C}', '\u{227D}'), ('\u{227E}', '\u{227F}'), ('\u{2280}', '\u{2281}'), ('\u{2282}', '\u{2283}'), ('\u{2284}', '\u{2285}'), ('\u{2286}', '\u{2287}'), ('\u{2288}', '\u{2289}'), ('\u{228A}', '\u{228B}'), ('\u{228F}', '\u{2290}'), ('\u{2291}', '\u{2292}'), ('\u{2298}', '\u{29B8}'), ('\u{22A2}', '\u{22A3}'), ('\u{22A6}', '\u{2ADE}'), ('\u{22A8}', '\u{2AE4}'), ('\u{22A9}', '\u{2AE3}'), ('\u{22AB}', '\u{2AE5}'), ('\u{22B0}', '\u{22B1}'), ('\u{22B2}', '\u{22B3}'), ('\u{22B4}', '\u{22B5}'), ('\u{22B6}', '\u{22B7}'), ('\u{22B8}', '\u{27DC}'), ('\u{22C9}', '\u{22CA}'), ('\u{22CB}', '\u{22CC}'), ('\u{22D0}', '\u{22D1}'), ('\u{22D6}', '\u{22D7}'), ('\u{22D8}', '\u{22D9}'), ('\u{22DA}', '\u{22DB}'), ('\u{22DC}', '\u{22DD}'), ('\u{22DE}', '\u{22DF}'), ('\u{22E0}', '\u{22E1}'), ('\u{22E2}', '\u{22E3}'), ('\u{22E4}', '\u{22E5}'), ('\u{22E6}', '\u{22E7}'), ('\u{22E8}', '\u{22E9}'), ('\u{22EA}', '\u{22EB}'), ('\u{22EC}', '\u{22ED}'), ('\u{22F0}', '\u{22F1}'), ('\u{22F2}', '\u{22FA}'), ('\u{22F3}', '\u{22FB}'), ('\u{22F4}', '\u{22FC}'), ('\u{22F6}', '\u{22FD}'), ('\u{22F7}', '\u{22FE}'), ('\u{2308}', '\u{2309}'), ('\u{230A}', '\u{230B}'), ('\u{2329}', '\u{232A}'), ('\u{2768}', '\u{2769}'), ('\u{276A}', '\u{276B}'), ('\u{276C}', '\u{276D}'), ('\u{276E}', '\u{276F}'), ('\u{2770}', '\u{2771}'), ('\u{2772}', '\u{2773}'), ('\u{2774}', '\u{2775}'), ('\u{27C3}', '\u{27C4}'), ('\u{27C5}', '\u{27C6}'), ('\u{27C8}', '\u{27C9}'), ('\u{27CB}', '\u{27CD}'), ('\u{27D5}', '\u{27D6}'), ('\u{27DD}', '\u{27DE}'), ('\u{27E2}', '\u{27E3}'), ('\u{27E4}', '\u{27E5}'), ('\u{27E6}', '\u{27E7}'), ('\u{27E8}', '\u{27E9}'), ('\u{27EA}', '\u{27EB}'), ('\u{27EC}', '\u{27ED}'), ('\u{27EE}', '\u{27EF}'), ('\u{2983}', '\u{2984}'), ('\u{2985}', '\u{2986}'), ('\u{2987}', '\u{2988}'), ('\u{2989}', '\u{298A}'), ('\u{298B}', '\u{298C}'), ('\u{298D}', '\u{2990}'), ('\u{298E}', '\u{298F}'), ('\u{2991}', '\u{2992}'), ('\u{2993}', '\u{2994}'), ('\u{2995}', '\u{2996}'), ('\u{2997}', '\u{2998}'), ('\u{29A4}', '\u{29A5}'), ('\u{29A8}', '\u{29A9}'), ('\u{29AA}', '\u{29AB}'), ('\u{29AC}', '\u{29AD}'), ('\u{29AE}', '\u{29AF}'), ('\u{29C0}', '\u{29C1}'), ('\u{29C4}', '\u{29C5}'), ('\u{29CF}', '\u{29D0}'), ('\u{29D1}', '\u{29D2}'), ('\u{29D4}', '\u{29D5}'), ('\u{29D8}', '\u{29D9}'), ('\u{29DA}', '\u{29DB}'), ('\u{29E8}', '\u{29E9}'), ('\u{29F8}', '\u{29F9}'), ('\u{29FC}', '\u{29FD}'), ('\u{2A2B}', '\u{2A2C}'), ('\u{2A2D}', '\u{2A2E}'), ('\u{2A34}', '\u{2A35}'), ('\u{2A3C}', '\u{2A3D}'), ('\u{2A64}', '\u{2A65}'), ('\u{2A79}', '\u{2A7A}'), ('\u{2A7B}', '\u{2A7C}'), ('\u{2A7D}', '\u{2A7E}'), ('\u{2A7F}', '\u{2A80}'), ('\u{2A81}', '\u{2A82}'), ('\u{2A83}', '\u{2A84}'), ('\u{2A85}', '\u{2A86}'), ('\u{2A87}', '\u{2A88}'), ('\u{2A89}', '\u{2A8A}'), ('\u{2A8B}', '\u{2A8C}'), ('\u{2A8D}', '\u{2A8E}'), ('\u{2A8F}', '\u{2A90}'), ('\u{2A91}', '\u{2A92}'), ('\u{2A93}', '\u{2A94}'), ('\u{2A95}', '\u{2A96}'), ('\u{2A97}', '\u{2A98}'), ('\u{2A99}', '\u{2A9A}'), ('\u{2A9B}', '\u{2A9C}'), ('\u{2A9D}', '\u{2A9E}'), ('\u{2A9F}', '\u{2AA0}'), ('\u{2AA1}', '\u{2AA2}'), ('\u{2AA6}', '\u{2AA7}'), ('\u{2AA8}', '\u{2AA9}'), ('\u{2AAA}', '\u{2AAB}'), ('\u{2AAC}', '\u{2AAD}'), ('\u{2AAF}', '\u{2AB0}'), ('\u{2AB1}', '\u{2AB2}'), ('\u{2AB3}', '\u{2AB4}'), ('\u{2AB5}', '\u{2AB6}'), ('\u{2AB7}', '\u{2AB8}'), ('\u{2AB9}', '\u{2ABA}'), ('\u{2ABB}', '\u{2ABC}'), ('\u{2ABD}', '\u{2ABE}'), ('\u{2ABF}', '\u{2AC0}'), ('\u{2AC1}', '\u{2AC2}'), ('\u{2AC3}', '\u{2AC4}'), ('\u{2AC5}', '\u{2AC6}'), ('\u{2AC7}', '\u{2AC8}'), ('\u{2AC9}', '\u{2ACA}'), ('\u{2ACB}', '\u{2ACC}'), ('\u{2ACD}', '\u{2ACE}'), ('\u{2ACF}', '\u{2AD0}'), ('\u{2AD1}', '\u{2AD2}'), ('\u{2AD3}', '\u{2AD4}'), ('\u{2AD5}', '\u{2AD6}'), ('\u{2AEC}', '\u{2AED}'), ('\u{2AF7}', '\u{2AF8}'), ('\u{2AF9}', '\u{2AFA}'), ('\u{2E02}', '\u{2E03}'), ('\u{2E04}', '\u{2E05}'), ('\u{2E09}', '\u{2E0A}'), ('\u{2E0C}', '\u{2E0D}'), ('\u{2E1C}', '\u{2E1D}'), ('\u{2E20}', '\u{2E21}'), ('\u{2E22}', '\u{2E23}'), ('\u{2E24}', '\u{2E25}'), ('\u{2E26}', '\u{2E27}'), ('\u{2E28}', '\u{2E29}'), ('\u{2E55}', '\u{2E56}'), ('\u{2E57}', '\u{2E58}'), ('\u{2E59}', '\u{2E5A}'), ('\u{2E5B}', '\u{2E5C}'), ('\u{3008}', '\u{3009}'), ('\u{300A}', '\u{300B}'), ('\u{300C}', '\u{300D}'), ('\u{300E}', '\u{300F}'), ('\u{3010}', '\u{3011}'), ('\u{3014}', '\u{3015}'), ('\u{3016}', '\u{3017}'), ('\u{3018}', '\u{3019}'), ('\u{301A}', '\u{301B}'), ('\u{FE59}', '\u{FE5A}'), ('\u{FE5B}', '\u{FE5C}'), ('\u{FE5D}', '\u{FE5E}'), ('\u{FE64}', '\u{FE65}'), ('\u{FF08}', '\u{FF09}'), ('\u{FF1C}', '\u{FF1E}'), ('\u{FF3B}', '\u{FF3D}'), ('\u{FF5B}', '\u{FF5D}'), ('\u{FF5F}', '\u{FF60}'), ('\u{FF62}', '\u{FF63}'), ]; const OTHER: &[char] = &[ '\u{2140}', '\u{2201}', '\u{2202}', '\u{2203}', '\u{2204}', '\u{2211}', '\u{2216}', '\u{221A}', '\u{221B}', '\u{221C}', '\u{221D}', '\u{2226}', '\u{222B}', '\u{222C}', '\u{222D}', '\u{222E}', '\u{222F}', '\u{2230}', '\u{2231}', '\u{2232}', '\u{2233}', '\u{2239}', '\u{223B}', '\u{223E}', '\u{223F}', '\u{2240}', '\u{2241}', '\u{2242}', '\u{2244}', '\u{2246}', '\u{2247}', '\u{2248}', '\u{2249}', '\u{224A}', '\u{224B}', '\u{225F}', '\u{2260}', '\u{2262}', '\u{228C}', '\u{22A7}', '\u{22AA}', '\u{22AC}', '\u{22AD}', '\u{22AE}', '\u{22AF}', '\u{22BE}', '\u{22BF}', '\u{22F5}', '\u{22F8}', '\u{22F9}', '\u{22FF}', '\u{2320}', '\u{2321}', '\u{27C0}', '\u{27CC}', '\u{27D3}', '\u{27D4}', '\u{299C}', '\u{299D}', '\u{299E}', '\u{299F}', '\u{29A2}', '\u{29A6}', '\u{29A7}', '\u{29C2}', '\u{29C3}', '\u{29C9}', '\u{29CE}', '\u{29DC}', '\u{29E1}', '\u{29E3}', '\u{29E4}', '\u{29E5}', '\u{29F4}', '\u{29F6}', '\u{29F7}', '\u{2A0A}', '\u{2A0B}', '\u{2A0C}', '\u{2A0D}', '\u{2A0E}', '\u{2A0F}', '\u{2A10}', '\u{2A11}', '\u{2A12}', '\u{2A13}', '\u{2A14}', '\u{2A15}', '\u{2A16}', '\u{2A17}', '\u{2A18}', '\u{2A19}', '\u{2A1A}', '\u{2A1B}', '\u{2A1C}', '\u{2A1E}', '\u{2A1F}', '\u{2A20}', '\u{2A21}', '\u{2A24}', '\u{2A26}', '\u{2A29}', '\u{2A3E}', '\u{2A57}', '\u{2A58}', '\u{2A6A}', '\u{2A6B}', '\u{2A6C}', '\u{2A6D}', '\u{2A6F}', '\u{2A70}', '\u{2A73}', '\u{2A74}', '\u{2AA3}', '\u{2ADC}', '\u{2AE2}', '\u{2AE6}', '\u{2AF3}', '\u{2AFB}', '\u{2AFD}', '\u{1D6DB}', '\u{1D715}', '\u{1D74F}', '\u{1D789}', '\u{1D7C3}', ]; /// Returns a bidi mirrored character. /// /// Based on . pub fn get_mirrored(c: char) -> Option { if let Ok(idx) = PAIRS.binary_search_by(|v| v.0.cmp(&c)) { return Some(PAIRS[idx].1); } if let Ok(idx) = PAIRS.binary_search_by(|v| v.1.cmp(&c)) { return Some(PAIRS[idx].0); } None } /// Checks that character is bidi mirrored. /// /// Based on . pub fn is_mirroring(c: char) -> bool { PAIRS.binary_search_by(|v| v.0.cmp(&c)).is_ok() || PAIRS.binary_search_by(|v| v.1.cmp(&c)).is_ok() || OTHER.binary_search_by(|v| v.cmp(&c)).is_ok() }