diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
commit | 9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/rust/unicase/src | |
parent | Initial commit. (diff) | |
download | thunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.tar.xz thunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/unicase/src')
-rw-r--r-- | third_party/rust/unicase/src/ascii.rs | 187 | ||||
-rw-r--r-- | third_party/rust/unicase/src/lib.rs | 465 | ||||
-rw-r--r-- | third_party/rust/unicase/src/unicode/map.rs | 1995 | ||||
-rw-r--r-- | third_party/rust/unicase/src/unicode/mod.rs | 201 |
4 files changed, 2848 insertions, 0 deletions
diff --git a/third_party/rust/unicase/src/ascii.rs b/third_party/rust/unicase/src/ascii.rs new file mode 100644 index 0000000000..8940733c38 --- /dev/null +++ b/third_party/rust/unicase/src/ascii.rs @@ -0,0 +1,187 @@ +use alloc::string::String; +#[cfg(__unicase__iter_cmp)] +use core::cmp::Ordering; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::ops::{Deref, DerefMut}; +use core::str::FromStr; +#[cfg(not(__unicase__core_and_alloc))] +#[allow(deprecated, unused)] +use std::ascii::AsciiExt; + +use super::{Ascii, Encoding, UniCase}; + +impl<S> Ascii<S> { + #[inline] + #[cfg(__unicase__const_fns)] + pub const fn new(s: S) -> Ascii<S> { + Ascii(s) + } + + /// Construct a new `Ascii`. + /// + /// For Rust versions >= 1.31, this is a `const fn`. + #[inline] + #[cfg(not(__unicase__const_fns))] + pub fn new(s: S) -> Ascii<S> { + Ascii(s) + } + + #[cfg(__unicase_const_fns)] + pub const fn into_unicase(self) -> UniCase<S> { + UniCase(Encoding::Ascii(self)) + } + + #[cfg(not(__unicase_const_fns))] + pub fn into_unicase(self) -> UniCase<S> { + UniCase(Encoding::Ascii(self)) + } + + #[inline] + pub fn into_inner(self) -> S { + self.0 + } +} + +impl<S> Deref for Ascii<S> { + type Target = S; + #[inline] + fn deref<'a>(&'a self) -> &'a S { + &self.0 + } +} + +impl<S> DerefMut for Ascii<S> { + #[inline] + fn deref_mut<'a>(&'a mut self) -> &'a mut S { + &mut self.0 + } +} + +#[cfg(__unicase__iter_cmp)] +impl<T: AsRef<str>> PartialOrd for Ascii<T> { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[cfg(__unicase__iter_cmp)] +impl<T: AsRef<str>> Ord for Ascii<T> { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + let self_chars = self.as_ref().chars().map(|c| c.to_ascii_lowercase()); + let other_chars = other.as_ref().chars().map(|c| c.to_ascii_lowercase()); + self_chars.cmp(other_chars) + } +} + +impl<S: AsRef<str>> AsRef<str> for Ascii<S> { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_ref() + } + +} + +impl<S: fmt::Display> fmt::Display for Ascii<S> { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, fmt) + } +} + +impl<S1: AsRef<str>> PartialEq<Ascii<S1>> for String { + #[inline] + fn eq(&self, other: &Ascii<S1>) -> bool { + other == self + } +} + +impl<'a, S1: AsRef<str>> PartialEq<Ascii<S1>> for &'a str { + #[inline] + fn eq(&self, other: &Ascii<S1>) -> bool { + other == self + } +} + +impl<S1: AsRef<str>, S2: AsRef<str>> PartialEq<S2> for Ascii<S1> { + #[inline] + fn eq(&self, other: &S2) -> bool { + self.as_ref().eq_ignore_ascii_case(other.as_ref()) + } +} + +impl<S: AsRef<str>> Eq for Ascii<S> {} + +impl<S: FromStr> FromStr for Ascii<S> { + type Err = <S as FromStr>::Err; + fn from_str(s: &str) -> Result<Ascii<S>, <S as FromStr>::Err> { + s.parse().map(Ascii) + } +} + +impl<S: AsRef<str>> Hash for Ascii<S> { + #[inline] + fn hash<H: Hasher>(&self, hasher: &mut H) { + for byte in self.as_ref().bytes().map(|b| b.to_ascii_lowercase()) { + hasher.write_u8(byte); + } + } +} + +#[cfg(test)] +mod tests { + use ::Ascii; + use std::hash::{Hash, Hasher}; + #[cfg(not(__unicase__default_hasher))] + use std::hash::SipHasher as DefaultHasher; + #[cfg(__unicase__default_hasher)] + use std::collections::hash_map::DefaultHasher; + + fn hash<T: Hash>(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() + } + + #[test] + fn test_case_insensitive() { + let a = Ascii("foobar"); + let b = Ascii("FOOBAR"); + + assert_eq!(a, b); + assert_eq!(hash(&a), hash(&b)); + + assert_eq!(a, "fooBar"); + assert_eq!("fooBar", a); + assert_eq!(String::from("fooBar"), a); + assert_eq!(a, String::from("fooBar")); + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_ascii_eq(b: &mut ::test::Bencher) { + b.bytes = b"foobar".len() as u64; + b.iter(|| assert_eq!(Ascii("foobar"), Ascii("FOOBAR"))); + } + + #[cfg(__unicase__iter_cmp)] + #[test] + fn test_case_cmp() { + assert!(Ascii("foobar") == Ascii("FOOBAR")); + assert!(Ascii("a") < Ascii("B")); + + assert!(Ascii("A") < Ascii("b")); + assert!(Ascii("aa") > Ascii("a")); + + assert!(Ascii("a") < Ascii("aa")); + assert!(Ascii("a") < Ascii("AA")); + } + + #[cfg(__unicase__const_fns)] + #[test] + fn test_ascii_new_const() { + const _ASCII: Ascii<&'static str> = Ascii::new(""); + } +} diff --git a/third_party/rust/unicase/src/lib.rs b/third_party/rust/unicase/src/lib.rs new file mode 100644 index 0000000000..0c02b5ebca --- /dev/null +++ b/third_party/rust/unicase/src/lib.rs @@ -0,0 +1,465 @@ +#![cfg_attr(test, deny(missing_docs))] +#![cfg_attr(test, deny(warnings))] +#![doc(html_root_url = "https://docs.rs/unicase/2.6.0")] +#![cfg_attr(feature = "nightly", feature(test))] +#![cfg_attr( + all( + __unicase__core_and_alloc, + not(test), + ), + no_std, +)] + +//! # UniCase +//! +//! UniCase provides a way of specifying strings that are case-insensitive. +//! +//! UniCase supports full [Unicode case +//! folding](https://www.w3.org/International/wiki/Case_folding). It can also +//! utilize faster ASCII case comparisons, if both strings are ASCII. +//! +//! Using the `UniCase::new()` constructor will check the string to see if it +//! is all ASCII. When a `UniCase` is compared against another, if both are +//! ASCII, it will use the faster comparison. +//! +//! There also exists the `Ascii` type in this crate, which will always assume +//! to use the ASCII case comparisons, if the encoding is already known. +//! +//! ## Example +//! +//! ```rust +//! use unicase::UniCase; +//! +//! let a = UniCase::new("Maße"); +//! let b = UniCase::new("MASSE"); +//! let c = UniCase::new("mase"); +//! +//! assert_eq!(a, b); +//! assert!(b != c); +//! ``` +//! +//! ## Ascii +//! +//! ```rust +//! use unicase::Ascii; +//! +//! let a = Ascii::new("foobar"); +//! let b = Ascii::new("FoObAr"); +//! +//! assert_eq!(a, b); +//! ``` + +#[cfg(feature = "nightly")] +extern crate test; + +#[cfg(all(__unicase__core_and_alloc, not(test)))] +extern crate alloc; +#[cfg(all(__unicase__core_and_alloc, not(test)))] +use alloc::string::String; + +#[cfg(not(all(__unicase__core_and_alloc, not(test))))] +extern crate std as alloc; +#[cfg(not(all(__unicase__core_and_alloc, not(test))))] +extern crate std as core; + +use alloc::borrow::Cow; +#[cfg(__unicase__iter_cmp)] +use core::cmp::Ordering; +use core::fmt; +use core::hash::{Hash, Hasher}; +use core::ops::{Deref, DerefMut}; +use core::str::FromStr; + +use self::unicode::Unicode; + +mod ascii; +mod unicode; + +/// Case Insensitive wrapper of strings. +#[derive(Clone, Copy)] +pub struct UniCase<S>(Encoding<S>); + +/// Case Insensitive wrapper of Ascii strings. +#[derive(Clone, Copy, Debug, Default)] +pub struct Ascii<S>(S); + +/// Compare two string-like types for case-less equality, using unicode folding. +/// +/// Equivalent to `UniCase::new(left) == UniCase::new(right)`. +/// +/// Note: This will perform a scan for ASCII characters before doing the +/// the comparison. See `UniCase` for more information. +#[inline] +pub fn eq<S: AsRef<str> + ?Sized>(left: &S, right: &S) -> bool { + UniCase::new(left) == UniCase::new(right) +} + +/// Compare two string-like types for case-less equality, ignoring ASCII case. +/// +/// Equivalent to `Ascii::new(left) == Ascii::new(right)`. +#[inline] +pub fn eq_ascii<S: AsRef<str> + ?Sized>(left: &S, right: &S) -> bool { + Ascii(left) == Ascii(right) +} + +#[derive(Clone, Copy, Debug)] +enum Encoding<S> { + Ascii(Ascii<S>), + Unicode(Unicode<S>), +} + +macro_rules! inner { + + (mut $e:expr) => ({ + match &mut $e { + &mut Encoding::Ascii(ref mut s) => &mut s.0, + &mut Encoding::Unicode(ref mut s) => &mut s.0, + } + }); + ($e:expr) => ({ + match &$e { + &Encoding::Ascii(ref s) => &s.0, + &Encoding::Unicode(ref s) => &s.0, + } + }); +} + +impl<S: AsRef<str> + Default> Default for UniCase<S> { + fn default() -> Self { + Self::new(Default::default()) + } +} + +impl<S: AsRef<str>> UniCase<S> { + /// Creates a new `UniCase`. + /// + /// Note: This scans the text to determine if it is all ASCII or not. + pub fn new(s: S) -> UniCase<S> { + #[cfg(not(__unicase__core_and_alloc))] + #[allow(deprecated, unused)] + use std::ascii::AsciiExt; + + if s.as_ref().is_ascii() { + UniCase(Encoding::Ascii(Ascii(s))) + } else { + UniCase(Encoding::Unicode(Unicode(s))) + } + } +} + +impl<S> UniCase<S> { + /// Creates a new `UniCase`, skipping the ASCII check. + #[cfg(__unicase__const_fns)] + pub const fn unicode(s: S) -> UniCase<S> { + UniCase(Encoding::Unicode(Unicode(s))) + } + + /// Creates a new `UniCase`, skipping the ASCII check. + /// + /// For Rust versions >= 1.31, this is a `const fn`. + #[cfg(not(__unicase__const_fns))] + pub fn unicode(s: S) -> UniCase<S> { + UniCase(Encoding::Unicode(Unicode(s))) + } + + /// Creates a new `UniCase` which performs only ASCII case folding. + #[cfg(__unicase__const_fns)] + pub const fn ascii(s: S) -> UniCase<S> { + UniCase(Encoding::Ascii(Ascii(s))) + } + + /// Creates a new `UniCase` which performs only ASCII case folding. + /// + /// For Rust versions >= 1.31, this is a `const fn`. + #[cfg(not(__unicase__const_fns))] + pub fn ascii(s: S) -> UniCase<S> { + UniCase(Encoding::Ascii(Ascii(s))) + } + + /// Return `true` if this instance will only perform ASCII case folding. + pub fn is_ascii(&self) -> bool { + match self.0 { + Encoding::Ascii(_) => true, + Encoding::Unicode(_) => false, + } + } + + /// Unwraps the inner value held by this `UniCase`. + #[inline] + pub fn into_inner(self) -> S { + match self.0 { + Encoding::Ascii(s) => s.0, + Encoding::Unicode(s) => s.0, + } + } +} + +impl<S> Deref for UniCase<S> { + type Target = S; + #[inline] + fn deref<'a>(&'a self) -> &'a S { + inner!(self.0) + } +} + +impl<S> DerefMut for UniCase<S> { + #[inline] + fn deref_mut<'a>(&'a mut self) -> &'a mut S { + inner!(mut self.0) + } +} + +impl<S: AsRef<str>> AsRef<str> for UniCase<S> { + #[inline] + fn as_ref(&self) -> &str { + inner!(self.0).as_ref() + } + +} + +impl<S: fmt::Debug> fmt::Debug for UniCase<S> { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(inner!(self.0), fmt) + } +} + +impl<S: fmt::Display> fmt::Display for UniCase<S> { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(inner!(self.0), fmt) + } +} + + +impl<S1: AsRef<str>, S2: AsRef<str>> PartialEq<UniCase<S2>> for UniCase<S1> { + #[inline] + fn eq(&self, other: &UniCase<S2>) -> bool { + match (&self.0, &other.0) { + (&Encoding::Ascii(ref x), &Encoding::Ascii(ref y)) => x == y, + (&Encoding::Unicode(ref x), &Encoding::Unicode(ref y)) => x == y, + (&Encoding::Ascii(ref x), &Encoding::Unicode(ref y)) => &Unicode(x.as_ref()) == y, + (&Encoding::Unicode(ref x), &Encoding::Ascii(ref y)) => x == &Unicode(y.as_ref()), + } + } +} + +impl<S: AsRef<str>> Eq for UniCase<S> {} + +impl<S: AsRef<str>> Hash for UniCase<S> { + #[inline] + fn hash<H: Hasher>(&self, hasher: &mut H) { + match self.0 { + Encoding::Ascii(ref s) => s.hash(hasher), + Encoding::Unicode(ref s) => s.hash(hasher) + } + } +} + +impl<S> From<Ascii<S>> for UniCase<S> { + fn from(ascii: Ascii<S>) -> Self { + UniCase(Encoding::Ascii(ascii)) + } +} + +macro_rules! from_impl { + ($from:ty => $to:ty; $by:ident) => ( + impl<'a> From<$from> for UniCase<$to> { + fn from(s: $from) -> Self { + UniCase::unicode(s.$by()) + } + } + ); + ($from:ty => $to:ty) => ( from_impl!($from => $to; into); ) +} + +macro_rules! into_impl { + ($to:ty) => ( + impl<'a> Into<$to> for UniCase<$to> { + fn into(self) -> $to { + self.into_inner() + } + } + ); +} + +impl<S: AsRef<str>> From<S> for UniCase<S> { + fn from(s: S) -> Self { + UniCase::unicode(s) + } +} + +from_impl!(&'a str => Cow<'a, str>); +from_impl!(String => Cow<'a, str>); +from_impl!(&'a str => String); +from_impl!(Cow<'a, str> => String; into_owned); +from_impl!(&'a String => &'a str; as_ref); + +into_impl!(&'a str); +into_impl!(String); +into_impl!(Cow<'a, str>); + +#[cfg(__unicase__iter_cmp)] +impl<T: AsRef<str>> PartialOrd for UniCase<T> { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[cfg(__unicase__iter_cmp)] +impl<T: AsRef<str>> Ord for UniCase<T> { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + match (&self.0, &other.0) { + (&Encoding::Ascii(ref x), &Encoding::Ascii(ref y)) => x.cmp(y), + (&Encoding::Unicode(ref x), &Encoding::Unicode(ref y)) => x.cmp(y), + (&Encoding::Ascii(ref x), &Encoding::Unicode(ref y)) => Unicode(x.as_ref()).cmp(&Unicode(y.0.as_ref())), + (&Encoding::Unicode(ref x), &Encoding::Ascii(ref y)) => Unicode(x.0.as_ref()).cmp(&Unicode(y.as_ref())), + } + } +} + + + +impl<S: FromStr + AsRef<str>> FromStr for UniCase<S> { + type Err = <S as FromStr>::Err; + fn from_str(s: &str) -> Result<UniCase<S>, Self::Err> { + s.parse().map(UniCase::new) + } +} + +#[cfg(test)] +mod tests { + use super::UniCase; + use std::hash::{Hash, Hasher}; + #[cfg(not(__unicase__default_hasher))] + use std::hash::SipHasher as DefaultHasher; + #[cfg(__unicase__default_hasher)] + use std::collections::hash_map::DefaultHasher; + + fn hash<T: Hash>(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() + } + + #[test] + fn test_copy_for_refs() { + fn foo<T>(_: UniCase<T>) {} + + let a = UniCase::new("foobar"); + foo(a); + foo(a); + } + + #[test] + fn test_eq_ascii() { + let a = UniCase::new("foobar"); + let b = UniCase::new("FOOBAR"); + let c = UniCase::ascii("FoObAr"); + + assert_eq!(a, b); + assert_eq!(b, a); + assert_eq!(a, c); + assert_eq!(c, a); + assert_eq!(hash(&a), hash(&b)); + assert_eq!(hash(&a), hash(&c)); + assert!(a.is_ascii()); + assert!(b.is_ascii()); + assert!(c.is_ascii()); + } + + + #[test] + fn test_eq_unicode() { + let a = UniCase::new("στιγμας"); + let b = UniCase::new("στιγμασ"); + assert_eq!(a, b); + assert_eq!(b, a); + assert_eq!(hash(&a), hash(&b)); + } + + #[test] + fn test_eq_unicode_left_is_substring() { + // https://github.com/seanmonstar/unicase/issues/38 + let a = UniCase::unicode("foo"); + let b = UniCase::unicode("foobar"); + + assert!(a != b); + assert!(b != a); + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_unicase_ascii(b: &mut ::test::Bencher) { + b.bytes = b"foobar".len() as u64; + let x = UniCase::new("foobar"); + let y = UniCase::new("FOOBAR"); + b.iter(|| assert_eq!(x, y)); + } + + #[cfg(feature = "nightly")] + static SUBJECT: &'static [u8] = b"ffoo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz oo bar baz quux herp derp"; + + #[cfg(feature = "nightly")] + #[inline(never)] + fn is_ascii(bytes: &[u8]) -> bool { + #[allow(unused, deprecated)] + use std::ascii::AsciiExt; + bytes.is_ascii() + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_is_ascii(b: &mut ::test::Bencher) { + b.iter(|| assert!(is_ascii(SUBJECT))); + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_is_utf8(b: &mut ::test::Bencher) { + b.iter(|| assert!(::std::str::from_utf8(SUBJECT).is_ok())); + } + + #[cfg(__unicase__iter_cmp)] + #[test] + fn test_case_cmp() { + assert!(UniCase::new("a") < UniCase::new("B")); + + assert!(UniCase::new("A") < UniCase::new("b")); + assert!(UniCase::new("aa") > UniCase::new("a")); + + assert!(UniCase::new("a") < UniCase::new("aa")); + assert!(UniCase::new("a") < UniCase::new("AA")); + } + + #[test] + fn test_from_impls() { + let view: &'static str = "foobar"; + let _: UniCase<&'static str> = view.into(); + let _: UniCase<&str> = view.into(); + let _: UniCase<String> = view.into(); + + let owned: String = view.to_owned(); + let _: UniCase<&str> = (&owned).into(); + let _: UniCase<String> = owned.into(); + } + + #[test] + fn test_into_impls() { + let view: UniCase<&'static str> = UniCase::new("foobar"); + let _: &'static str = view.into(); + let _: &str = view.into(); + + let owned: UniCase<String> = "foobar".into(); + let _: String = owned.clone().into(); + let _: &str = owned.as_ref(); + } + + #[cfg(__unicase__const_fns)] + #[test] + fn test_unicase_unicode_const() { + const _UNICASE: UniCase<&'static str> = UniCase::unicode(""); + } +} diff --git a/third_party/rust/unicase/src/unicode/map.rs b/third_party/rust/unicase/src/unicode/map.rs new file mode 100644 index 0000000000..e43e0b7fe3 --- /dev/null +++ b/third_party/rust/unicase/src/unicode/map.rs @@ -0,0 +1,1995 @@ +// Generated by scripts/mapgen.py +// 2019-08-31 + +use super::fold::Fold; + +use core::char; +pub fn lookup(orig: char) -> Fold { + // The code below is is intended to reduce the binary size from that of a simple 1:1 lookup table. + // It exploits two facts: + // 1. Many of the mappings form ranges mapped to other ranges. + // To benefit from this, we match on ranges instead of single numbers. + // Alone, this decreases the binary size but results in performance regression over the simple 1:1 lookup. + // 2. Most of the mappings are from relatively small chars (0 - 0x2CFF). + // To benefit from this, we use a jump table based on the high byte for this range. + // This more than recovers the performance regression from exploting fact #1, at least in the tested benchmark. + let from = orig as u32; + if from <= 0x2CFF { + let from = from as u16; + let high_byte = (from >> 8) as u8; + let low_byte = (from & 0xff) as u8; + let single_char: u16 = match high_byte { + 0x00 => { + match low_byte { + x @ _ if 0x41 <= x && x <= 0x5a => from.wrapping_add(0x0020), + 0xb5 => 0x03bc, + x @ _ if 0xc0 <= x && x <= 0xd6 => from.wrapping_add(0x0020), + x @ _ if 0xd8 <= x && x <= 0xde => from.wrapping_add(0x0020), + 0xdf => return Fold::Two('\u{0073}', '\u{0073}',), + _ => from + } + } + 0x01 => { + match low_byte { + x @ _ if x <= 0x2e => (from | 1), + 0x30 => return Fold::Two('\u{0069}', '\u{0307}',), + x @ _ if 0x32 <= x && x <= 0x36 => (from | 1), + x @ _ if 0x39 <= x && x <= 0x47 => ((from+1) & !1), + 0x49 => return Fold::Two('\u{02bc}', '\u{006e}',), + x @ _ if 0x4a <= x && x <= 0x76 => (from | 1), + 0x78 => 0x00ff, + x @ _ if 0x79 <= x && x <= 0x7d => ((from+1) & !1), + 0x7f => 0x0073, + 0x81 => 0x0253, + x @ _ if 0x82 <= x && x <= 0x84 => (from | 1), + 0x86 => 0x0254, + 0x87 => 0x0188, + x @ _ if 0x89 <= x && x <= 0x8a => from.wrapping_add(0x00cd), + 0x8b => 0x018c, + 0x8e => 0x01dd, + 0x8f => 0x0259, + 0x90 => 0x025b, + 0x91 => 0x0192, + 0x93 => 0x0260, + 0x94 => 0x0263, + 0x96 => 0x0269, + 0x97 => 0x0268, + 0x98 => 0x0199, + 0x9c => 0x026f, + 0x9d => 0x0272, + 0x9f => 0x0275, + x @ _ if 0xa0 <= x && x <= 0xa4 => (from | 1), + 0xa6 => 0x0280, + 0xa7 => 0x01a8, + 0xa9 => 0x0283, + 0xac => 0x01ad, + 0xae => 0x0288, + 0xaf => 0x01b0, + x @ _ if 0xb1 <= x && x <= 0xb2 => from.wrapping_add(0x00d9), + x @ _ if 0xb3 <= x && x <= 0xb5 => ((from+1) & !1), + 0xb7 => 0x0292, + 0xb8 => 0x01b9, + 0xbc => 0x01bd, + 0xc4 => 0x01c6, + 0xc5 => 0x01c6, + 0xc7 => 0x01c9, + 0xc8 => 0x01c9, + 0xca => 0x01cc, + x @ _ if 0xcb <= x && x <= 0xdb => ((from+1) & !1), + x @ _ if 0xde <= x && x <= 0xee => (from | 1), + 0xf0 => return Fold::Two('\u{006a}', '\u{030c}',), + 0xf1 => 0x01f3, + x @ _ if 0xf2 <= x && x <= 0xf4 => (from | 1), + 0xf6 => 0x0195, + 0xf7 => 0x01bf, + x @ _ if 0xf8 <= x => (from | 1), + _ => from + } + } + 0x02 => { + match low_byte { + x @ _ if x <= 0x1e => (from | 1), + 0x20 => 0x019e, + x @ _ if 0x22 <= x && x <= 0x32 => (from | 1), + 0x3a => 0x2c65, + 0x3b => 0x023c, + 0x3d => 0x019a, + 0x3e => 0x2c66, + 0x41 => 0x0242, + 0x43 => 0x0180, + 0x44 => 0x0289, + 0x45 => 0x028c, + x @ _ if 0x46 <= x && x <= 0x4e => (from | 1), + _ => from + } + } + 0x03 => { + match low_byte { + 0x45 => 0x03b9, + x @ _ if 0x70 <= x && x <= 0x72 => (from | 1), + 0x76 => 0x0377, + 0x7f => 0x03f3, + 0x86 => 0x03ac, + x @ _ if 0x88 <= x && x <= 0x8a => from.wrapping_add(0x0025), + 0x8c => 0x03cc, + x @ _ if 0x8e <= x && x <= 0x8f => from.wrapping_add(0x003f), + 0x90 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0301}',), + x @ _ if 0x91 <= x && x <= 0xa1 => from.wrapping_add(0x0020), + x @ _ if 0xa3 <= x && x <= 0xab => from.wrapping_add(0x0020), + 0xb0 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0301}',), + 0xc2 => 0x03c3, + 0xcf => 0x03d7, + 0xd0 => 0x03b2, + 0xd1 => 0x03b8, + 0xd5 => 0x03c6, + 0xd6 => 0x03c0, + x @ _ if 0xd8 <= x && x <= 0xee => (from | 1), + 0xf0 => 0x03ba, + 0xf1 => 0x03c1, + 0xf4 => 0x03b8, + 0xf5 => 0x03b5, + 0xf7 => 0x03f8, + 0xf9 => 0x03f2, + 0xfa => 0x03fb, + x @ _ if 0xfd <= x => from.wrapping_sub(0x0082), + _ => from + } + } + 0x04 => { + match low_byte { + x @ _ if x <= 0x0f => from.wrapping_add(0x0050), + x @ _ if 0x10 <= x && x <= 0x2f => from.wrapping_add(0x0020), + x @ _ if 0x60 <= x && x <= 0x80 => (from | 1), + x @ _ if 0x8a <= x && x <= 0xbe => (from | 1), + 0xc0 => 0x04cf, + x @ _ if 0xc1 <= x && x <= 0xcd => ((from+1) & !1), + x @ _ if 0xd0 <= x => (from | 1), + _ => from + } + } + 0x05 => { + match low_byte { + x @ _ if x <= 0x2e => (from | 1), + x @ _ if 0x31 <= x && x <= 0x56 => from.wrapping_add(0x0030), + 0x87 => return Fold::Two('\u{0565}', '\u{0582}',), + _ => from + } + } + 0x06 => { + from + } + 0x07 => { + from + } + 0x08 => { + from + } + 0x09 => { + from + } + 0x0a => { + from + } + 0x0b => { + from + } + 0x0c => { + from + } + 0x0d => { + from + } + 0x0e => { + from + } + 0x0f => { + from + } + 0x10 => { + match low_byte { + x @ _ if 0xa0 <= x && x <= 0xc5 => from.wrapping_add(0x1c60), + 0xc7 => 0x2d27, + 0xcd => 0x2d2d, + _ => from + } + } + 0x11 => { + from + } + 0x12 => { + from + } + 0x13 => { + match low_byte { + x @ _ if 0xf8 <= x && x <= 0xfd => from.wrapping_sub(0x0008), + _ => from + } + } + 0x14 => { + from + } + 0x15 => { + from + } + 0x16 => { + from + } + 0x17 => { + from + } + 0x18 => { + from + } + 0x19 => { + from + } + 0x1a => { + from + } + 0x1b => { + from + } + 0x1c => { + match low_byte { + 0x80 => 0x0432, + 0x81 => 0x0434, + 0x82 => 0x043e, + x @ _ if 0x83 <= x && x <= 0x84 => from.wrapping_sub(0x1842), + 0x85 => 0x0442, + 0x86 => 0x044a, + 0x87 => 0x0463, + 0x88 => 0xa64b, + x @ _ if 0x90 <= x && x <= 0xba => from.wrapping_sub(0x0bc0), + x @ _ if 0xbd <= x && x <= 0xbf => from.wrapping_sub(0x0bc0), + _ => from + } + } + 0x1d => { + from + } + 0x1e => { + match low_byte { + x @ _ if x <= 0x94 => (from | 1), + 0x96 => return Fold::Two('\u{0068}', '\u{0331}',), + 0x97 => return Fold::Two('\u{0074}', '\u{0308}',), + 0x98 => return Fold::Two('\u{0077}', '\u{030a}',), + 0x99 => return Fold::Two('\u{0079}', '\u{030a}',), + 0x9a => return Fold::Two('\u{0061}', '\u{02be}',), + 0x9b => 0x1e61, + 0x9e => return Fold::Two('\u{0073}', '\u{0073}',), + x @ _ if 0xa0 <= x && x <= 0xfe => (from | 1), + _ => from + } + } + 0x1f => { + match low_byte { + x @ _ if 0x08 <= x && x <= 0x0f => from.wrapping_sub(0x0008), + x @ _ if 0x18 <= x && x <= 0x1d => from.wrapping_sub(0x0008), + x @ _ if 0x28 <= x && x <= 0x2f => from.wrapping_sub(0x0008), + x @ _ if 0x38 <= x && x <= 0x3f => from.wrapping_sub(0x0008), + x @ _ if 0x48 <= x && x <= 0x4d => from.wrapping_sub(0x0008), + 0x50 => return Fold::Two('\u{03c5}', '\u{0313}',), + 0x52 => return Fold::Three('\u{03c5}', '\u{0313}', '\u{0300}',), + 0x54 => return Fold::Three('\u{03c5}', '\u{0313}', '\u{0301}',), + 0x56 => return Fold::Three('\u{03c5}', '\u{0313}', '\u{0342}',), + x @ _ if 0x59 <= x && x <= 0x5f => if (from & 1) == 1 { from.wrapping_sub(0x0008) } else { from }, + x @ _ if 0x68 <= x && x <= 0x6f => from.wrapping_sub(0x0008), + 0x80 => return Fold::Two('\u{1f00}', '\u{03b9}',), + 0x81 => return Fold::Two('\u{1f01}', '\u{03b9}',), + 0x82 => return Fold::Two('\u{1f02}', '\u{03b9}',), + 0x83 => return Fold::Two('\u{1f03}', '\u{03b9}',), + 0x84 => return Fold::Two('\u{1f04}', '\u{03b9}',), + 0x85 => return Fold::Two('\u{1f05}', '\u{03b9}',), + 0x86 => return Fold::Two('\u{1f06}', '\u{03b9}',), + 0x87 => return Fold::Two('\u{1f07}', '\u{03b9}',), + 0x88 => return Fold::Two('\u{1f00}', '\u{03b9}',), + 0x89 => return Fold::Two('\u{1f01}', '\u{03b9}',), + 0x8a => return Fold::Two('\u{1f02}', '\u{03b9}',), + 0x8b => return Fold::Two('\u{1f03}', '\u{03b9}',), + 0x8c => return Fold::Two('\u{1f04}', '\u{03b9}',), + 0x8d => return Fold::Two('\u{1f05}', '\u{03b9}',), + 0x8e => return Fold::Two('\u{1f06}', '\u{03b9}',), + 0x8f => return Fold::Two('\u{1f07}', '\u{03b9}',), + 0x90 => return Fold::Two('\u{1f20}', '\u{03b9}',), + 0x91 => return Fold::Two('\u{1f21}', '\u{03b9}',), + 0x92 => return Fold::Two('\u{1f22}', '\u{03b9}',), + 0x93 => return Fold::Two('\u{1f23}', '\u{03b9}',), + 0x94 => return Fold::Two('\u{1f24}', '\u{03b9}',), + 0x95 => return Fold::Two('\u{1f25}', '\u{03b9}',), + 0x96 => return Fold::Two('\u{1f26}', '\u{03b9}',), + 0x97 => return Fold::Two('\u{1f27}', '\u{03b9}',), + 0x98 => return Fold::Two('\u{1f20}', '\u{03b9}',), + 0x99 => return Fold::Two('\u{1f21}', '\u{03b9}',), + 0x9a => return Fold::Two('\u{1f22}', '\u{03b9}',), + 0x9b => return Fold::Two('\u{1f23}', '\u{03b9}',), + 0x9c => return Fold::Two('\u{1f24}', '\u{03b9}',), + 0x9d => return Fold::Two('\u{1f25}', '\u{03b9}',), + 0x9e => return Fold::Two('\u{1f26}', '\u{03b9}',), + 0x9f => return Fold::Two('\u{1f27}', '\u{03b9}',), + 0xa0 => return Fold::Two('\u{1f60}', '\u{03b9}',), + 0xa1 => return Fold::Two('\u{1f61}', '\u{03b9}',), + 0xa2 => return Fold::Two('\u{1f62}', '\u{03b9}',), + 0xa3 => return Fold::Two('\u{1f63}', '\u{03b9}',), + 0xa4 => return Fold::Two('\u{1f64}', '\u{03b9}',), + 0xa5 => return Fold::Two('\u{1f65}', '\u{03b9}',), + 0xa6 => return Fold::Two('\u{1f66}', '\u{03b9}',), + 0xa7 => return Fold::Two('\u{1f67}', '\u{03b9}',), + 0xa8 => return Fold::Two('\u{1f60}', '\u{03b9}',), + 0xa9 => return Fold::Two('\u{1f61}', '\u{03b9}',), + 0xaa => return Fold::Two('\u{1f62}', '\u{03b9}',), + 0xab => return Fold::Two('\u{1f63}', '\u{03b9}',), + 0xac => return Fold::Two('\u{1f64}', '\u{03b9}',), + 0xad => return Fold::Two('\u{1f65}', '\u{03b9}',), + 0xae => return Fold::Two('\u{1f66}', '\u{03b9}',), + 0xaf => return Fold::Two('\u{1f67}', '\u{03b9}',), + 0xb2 => return Fold::Two('\u{1f70}', '\u{03b9}',), + 0xb3 => return Fold::Two('\u{03b1}', '\u{03b9}',), + 0xb4 => return Fold::Two('\u{03ac}', '\u{03b9}',), + 0xb6 => return Fold::Two('\u{03b1}', '\u{0342}',), + 0xb7 => return Fold::Three('\u{03b1}', '\u{0342}', '\u{03b9}',), + x @ _ if 0xb8 <= x && x <= 0xb9 => from.wrapping_sub(0x0008), + x @ _ if 0xba <= x && x <= 0xbb => from.wrapping_sub(0x004a), + 0xbc => return Fold::Two('\u{03b1}', '\u{03b9}',), + 0xbe => 0x03b9, + 0xc2 => return Fold::Two('\u{1f74}', '\u{03b9}',), + 0xc3 => return Fold::Two('\u{03b7}', '\u{03b9}',), + 0xc4 => return Fold::Two('\u{03ae}', '\u{03b9}',), + 0xc6 => return Fold::Two('\u{03b7}', '\u{0342}',), + 0xc7 => return Fold::Three('\u{03b7}', '\u{0342}', '\u{03b9}',), + x @ _ if 0xc8 <= x && x <= 0xcb => from.wrapping_sub(0x0056), + 0xcc => return Fold::Two('\u{03b7}', '\u{03b9}',), + 0xd2 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0300}',), + 0xd3 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0301}',), + 0xd6 => return Fold::Two('\u{03b9}', '\u{0342}',), + 0xd7 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0342}',), + x @ _ if 0xd8 <= x && x <= 0xd9 => from.wrapping_sub(0x0008), + x @ _ if 0xda <= x && x <= 0xdb => from.wrapping_sub(0x0064), + 0xe2 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0300}',), + 0xe3 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0301}',), + 0xe4 => return Fold::Two('\u{03c1}', '\u{0313}',), + 0xe6 => return Fold::Two('\u{03c5}', '\u{0342}',), + 0xe7 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0342}',), + x @ _ if 0xe8 <= x && x <= 0xe9 => from.wrapping_sub(0x0008), + x @ _ if 0xea <= x && x <= 0xeb => from.wrapping_sub(0x0070), + 0xec => 0x1fe5, + 0xf2 => return Fold::Two('\u{1f7c}', '\u{03b9}',), + 0xf3 => return Fold::Two('\u{03c9}', '\u{03b9}',), + 0xf4 => return Fold::Two('\u{03ce}', '\u{03b9}',), + 0xf6 => return Fold::Two('\u{03c9}', '\u{0342}',), + 0xf7 => return Fold::Three('\u{03c9}', '\u{0342}', '\u{03b9}',), + x @ _ if 0xf8 <= x && x <= 0xf9 => from.wrapping_sub(0x0080), + x @ _ if 0xfa <= x && x <= 0xfb => from.wrapping_sub(0x007e), + 0xfc => return Fold::Two('\u{03c9}', '\u{03b9}',), + _ => from + } + } + 0x20 => { + from + } + 0x21 => { + match low_byte { + 0x26 => 0x03c9, + 0x2a => 0x006b, + 0x2b => 0x00e5, + 0x32 => 0x214e, + x @ _ if 0x60 <= x && x <= 0x6f => from.wrapping_add(0x0010), + 0x83 => 0x2184, + _ => from + } + } + 0x22 => { + from + } + 0x23 => { + from + } + 0x24 => { + match low_byte { + x @ _ if 0xb6 <= x && x <= 0xcf => from.wrapping_add(0x001a), + _ => from + } + } + 0x25 => { + from + } + 0x26 => { + from + } + 0x27 => { + from + } + 0x28 => { + from + } + 0x29 => { + from + } + 0x2a => { + from + } + 0x2b => { + from + } + 0x2c => { + match low_byte { + x @ _ if x <= 0x2e => from.wrapping_add(0x0030), + 0x60 => 0x2c61, + 0x62 => 0x026b, + 0x63 => 0x1d7d, + 0x64 => 0x027d, + x @ _ if 0x67 <= x && x <= 0x6b => ((from+1) & !1), + 0x6d => 0x0251, + 0x6e => 0x0271, + 0x6f => 0x0250, + 0x70 => 0x0252, + 0x72 => 0x2c73, + 0x75 => 0x2c76, + x @ _ if 0x7e <= x && x <= 0x7f => from.wrapping_sub(0x2a3f), + x @ _ if 0x80 <= x && x <= 0xe2 => (from | 1), + x @ _ if 0xeb <= x && x <= 0xed => ((from+1) & !1), + 0xf2 => 0x2cf3, + _ => from + } + } + _ => from + }; + Fold::One( char::from_u32(single_char as u32).unwrap_or(orig) ) + } else { + let single_char: u32 = match from { + x @ _ if 0xa640 <= x && x <= 0xa66c => (from | 1), + x @ _ if 0xa680 <= x && x <= 0xa69a => (from | 1), + x @ _ if 0xa722 <= x && x <= 0xa72e => (from | 1), + x @ _ if 0xa732 <= x && x <= 0xa76e => (from | 1), + x @ _ if 0xa779 <= x && x <= 0xa77b => ((from+1) & !1), + 0xa77d => 0x1d79, + x @ _ if 0xa77e <= x && x <= 0xa786 => (from | 1), + 0xa78b => 0xa78c, + 0xa78d => 0x0265, + x @ _ if 0xa790 <= x && x <= 0xa792 => (from | 1), + x @ _ if 0xa796 <= x && x <= 0xa7a8 => (from | 1), + 0xa7aa => 0x0266, + 0xa7ab => 0x025c, + 0xa7ac => 0x0261, + 0xa7ad => 0x026c, + 0xa7ae => 0x026a, + 0xa7b0 => 0x029e, + 0xa7b1 => 0x0287, + 0xa7b2 => 0x029d, + 0xa7b3 => 0xab53, + x @ _ if 0xa7b4 <= x && x <= 0xa7be => (from | 1), + 0xa7c2 => 0xa7c3, + 0xa7c4 => 0xa794, + 0xa7c5 => 0x0282, + 0xa7c6 => 0x1d8e, + x @ _ if 0xab70 <= x && x <= 0xabbf => from.wrapping_sub(0x97d0), + 0xfb00 => return Fold::Two('\u{0066}', '\u{0066}',), + 0xfb01 => return Fold::Two('\u{0066}', '\u{0069}',), + 0xfb02 => return Fold::Two('\u{0066}', '\u{006c}',), + 0xfb03 => return Fold::Three('\u{0066}', '\u{0066}', '\u{0069}',), + 0xfb04 => return Fold::Three('\u{0066}', '\u{0066}', '\u{006c}',), + 0xfb05 => return Fold::Two('\u{0073}', '\u{0074}',), + 0xfb06 => return Fold::Two('\u{0073}', '\u{0074}',), + 0xfb13 => return Fold::Two('\u{0574}', '\u{0576}',), + 0xfb14 => return Fold::Two('\u{0574}', '\u{0565}',), + 0xfb15 => return Fold::Two('\u{0574}', '\u{056b}',), + 0xfb16 => return Fold::Two('\u{057e}', '\u{0576}',), + 0xfb17 => return Fold::Two('\u{0574}', '\u{056d}',), + x @ _ if 0xff21 <= x && x <= 0xff3a => from.wrapping_add(0x0020), + x @ _ if 0x10400 <= x && x <= 0x10427 => from.wrapping_add(0x0028), + x @ _ if 0x104b0 <= x && x <= 0x104d3 => from.wrapping_add(0x0028), + x @ _ if 0x10c80 <= x && x <= 0x10cb2 => from.wrapping_add(0x0040), + x @ _ if 0x118a0 <= x && x <= 0x118bf => from.wrapping_add(0x0020), + x @ _ if 0x16e40 <= x && x <= 0x16e5f => from.wrapping_add(0x0020), + x @ _ if 0x1e900 <= x && x <= 0x1e921 => from.wrapping_add(0x0022), + _ => from + }; + Fold::One( char::from_u32(single_char).unwrap_or(orig) ) + } +} + +#[test] +fn lookup_consistency() { + fn lookup_naive(orig: char) -> Fold { + let single_char = match orig as u32 { + 0x0041 => 0x0061, + 0x0042 => 0x0062, + 0x0043 => 0x0063, + 0x0044 => 0x0064, + 0x0045 => 0x0065, + 0x0046 => 0x0066, + 0x0047 => 0x0067, + 0x0048 => 0x0068, + 0x0049 => 0x0069, + 0x004a => 0x006a, + 0x004b => 0x006b, + 0x004c => 0x006c, + 0x004d => 0x006d, + 0x004e => 0x006e, + 0x004f => 0x006f, + 0x0050 => 0x0070, + 0x0051 => 0x0071, + 0x0052 => 0x0072, + 0x0053 => 0x0073, + 0x0054 => 0x0074, + 0x0055 => 0x0075, + 0x0056 => 0x0076, + 0x0057 => 0x0077, + 0x0058 => 0x0078, + 0x0059 => 0x0079, + 0x005a => 0x007a, + 0x00b5 => 0x03bc, + 0x00c0 => 0x00e0, + 0x00c1 => 0x00e1, + 0x00c2 => 0x00e2, + 0x00c3 => 0x00e3, + 0x00c4 => 0x00e4, + 0x00c5 => 0x00e5, + 0x00c6 => 0x00e6, + 0x00c7 => 0x00e7, + 0x00c8 => 0x00e8, + 0x00c9 => 0x00e9, + 0x00ca => 0x00ea, + 0x00cb => 0x00eb, + 0x00cc => 0x00ec, + 0x00cd => 0x00ed, + 0x00ce => 0x00ee, + 0x00cf => 0x00ef, + 0x00d0 => 0x00f0, + 0x00d1 => 0x00f1, + 0x00d2 => 0x00f2, + 0x00d3 => 0x00f3, + 0x00d4 => 0x00f4, + 0x00d5 => 0x00f5, + 0x00d6 => 0x00f6, + 0x00d8 => 0x00f8, + 0x00d9 => 0x00f9, + 0x00da => 0x00fa, + 0x00db => 0x00fb, + 0x00dc => 0x00fc, + 0x00dd => 0x00fd, + 0x00de => 0x00fe, + 0x00df => return Fold::Two('\u{0073}', '\u{0073}',), + 0x0100 => 0x0101, + 0x0102 => 0x0103, + 0x0104 => 0x0105, + 0x0106 => 0x0107, + 0x0108 => 0x0109, + 0x010a => 0x010b, + 0x010c => 0x010d, + 0x010e => 0x010f, + 0x0110 => 0x0111, + 0x0112 => 0x0113, + 0x0114 => 0x0115, + 0x0116 => 0x0117, + 0x0118 => 0x0119, + 0x011a => 0x011b, + 0x011c => 0x011d, + 0x011e => 0x011f, + 0x0120 => 0x0121, + 0x0122 => 0x0123, + 0x0124 => 0x0125, + 0x0126 => 0x0127, + 0x0128 => 0x0129, + 0x012a => 0x012b, + 0x012c => 0x012d, + 0x012e => 0x012f, + 0x0130 => return Fold::Two('\u{0069}', '\u{0307}',), + 0x0132 => 0x0133, + 0x0134 => 0x0135, + 0x0136 => 0x0137, + 0x0139 => 0x013a, + 0x013b => 0x013c, + 0x013d => 0x013e, + 0x013f => 0x0140, + 0x0141 => 0x0142, + 0x0143 => 0x0144, + 0x0145 => 0x0146, + 0x0147 => 0x0148, + 0x0149 => return Fold::Two('\u{02bc}', '\u{006e}',), + 0x014a => 0x014b, + 0x014c => 0x014d, + 0x014e => 0x014f, + 0x0150 => 0x0151, + 0x0152 => 0x0153, + 0x0154 => 0x0155, + 0x0156 => 0x0157, + 0x0158 => 0x0159, + 0x015a => 0x015b, + 0x015c => 0x015d, + 0x015e => 0x015f, + 0x0160 => 0x0161, + 0x0162 => 0x0163, + 0x0164 => 0x0165, + 0x0166 => 0x0167, + 0x0168 => 0x0169, + 0x016a => 0x016b, + 0x016c => 0x016d, + 0x016e => 0x016f, + 0x0170 => 0x0171, + 0x0172 => 0x0173, + 0x0174 => 0x0175, + 0x0176 => 0x0177, + 0x0178 => 0x00ff, + 0x0179 => 0x017a, + 0x017b => 0x017c, + 0x017d => 0x017e, + 0x017f => 0x0073, + 0x0181 => 0x0253, + 0x0182 => 0x0183, + 0x0184 => 0x0185, + 0x0186 => 0x0254, + 0x0187 => 0x0188, + 0x0189 => 0x0256, + 0x018a => 0x0257, + 0x018b => 0x018c, + 0x018e => 0x01dd, + 0x018f => 0x0259, + 0x0190 => 0x025b, + 0x0191 => 0x0192, + 0x0193 => 0x0260, + 0x0194 => 0x0263, + 0x0196 => 0x0269, + 0x0197 => 0x0268, + 0x0198 => 0x0199, + 0x019c => 0x026f, + 0x019d => 0x0272, + 0x019f => 0x0275, + 0x01a0 => 0x01a1, + 0x01a2 => 0x01a3, + 0x01a4 => 0x01a5, + 0x01a6 => 0x0280, + 0x01a7 => 0x01a8, + 0x01a9 => 0x0283, + 0x01ac => 0x01ad, + 0x01ae => 0x0288, + 0x01af => 0x01b0, + 0x01b1 => 0x028a, + 0x01b2 => 0x028b, + 0x01b3 => 0x01b4, + 0x01b5 => 0x01b6, + 0x01b7 => 0x0292, + 0x01b8 => 0x01b9, + 0x01bc => 0x01bd, + 0x01c4 => 0x01c6, + 0x01c5 => 0x01c6, + 0x01c7 => 0x01c9, + 0x01c8 => 0x01c9, + 0x01ca => 0x01cc, + 0x01cb => 0x01cc, + 0x01cd => 0x01ce, + 0x01cf => 0x01d0, + 0x01d1 => 0x01d2, + 0x01d3 => 0x01d4, + 0x01d5 => 0x01d6, + 0x01d7 => 0x01d8, + 0x01d9 => 0x01da, + 0x01db => 0x01dc, + 0x01de => 0x01df, + 0x01e0 => 0x01e1, + 0x01e2 => 0x01e3, + 0x01e4 => 0x01e5, + 0x01e6 => 0x01e7, + 0x01e8 => 0x01e9, + 0x01ea => 0x01eb, + 0x01ec => 0x01ed, + 0x01ee => 0x01ef, + 0x01f0 => return Fold::Two('\u{006a}', '\u{030c}',), + 0x01f1 => 0x01f3, + 0x01f2 => 0x01f3, + 0x01f4 => 0x01f5, + 0x01f6 => 0x0195, + 0x01f7 => 0x01bf, + 0x01f8 => 0x01f9, + 0x01fa => 0x01fb, + 0x01fc => 0x01fd, + 0x01fe => 0x01ff, + 0x0200 => 0x0201, + 0x0202 => 0x0203, + 0x0204 => 0x0205, + 0x0206 => 0x0207, + 0x0208 => 0x0209, + 0x020a => 0x020b, + 0x020c => 0x020d, + 0x020e => 0x020f, + 0x0210 => 0x0211, + 0x0212 => 0x0213, + 0x0214 => 0x0215, + 0x0216 => 0x0217, + 0x0218 => 0x0219, + 0x021a => 0x021b, + 0x021c => 0x021d, + 0x021e => 0x021f, + 0x0220 => 0x019e, + 0x0222 => 0x0223, + 0x0224 => 0x0225, + 0x0226 => 0x0227, + 0x0228 => 0x0229, + 0x022a => 0x022b, + 0x022c => 0x022d, + 0x022e => 0x022f, + 0x0230 => 0x0231, + 0x0232 => 0x0233, + 0x023a => 0x2c65, + 0x023b => 0x023c, + 0x023d => 0x019a, + 0x023e => 0x2c66, + 0x0241 => 0x0242, + 0x0243 => 0x0180, + 0x0244 => 0x0289, + 0x0245 => 0x028c, + 0x0246 => 0x0247, + 0x0248 => 0x0249, + 0x024a => 0x024b, + 0x024c => 0x024d, + 0x024e => 0x024f, + 0x0345 => 0x03b9, + 0x0370 => 0x0371, + 0x0372 => 0x0373, + 0x0376 => 0x0377, + 0x037f => 0x03f3, + 0x0386 => 0x03ac, + 0x0388 => 0x03ad, + 0x0389 => 0x03ae, + 0x038a => 0x03af, + 0x038c => 0x03cc, + 0x038e => 0x03cd, + 0x038f => 0x03ce, + 0x0390 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0301}',), + 0x0391 => 0x03b1, + 0x0392 => 0x03b2, + 0x0393 => 0x03b3, + 0x0394 => 0x03b4, + 0x0395 => 0x03b5, + 0x0396 => 0x03b6, + 0x0397 => 0x03b7, + 0x0398 => 0x03b8, + 0x0399 => 0x03b9, + 0x039a => 0x03ba, + 0x039b => 0x03bb, + 0x039c => 0x03bc, + 0x039d => 0x03bd, + 0x039e => 0x03be, + 0x039f => 0x03bf, + 0x03a0 => 0x03c0, + 0x03a1 => 0x03c1, + 0x03a3 => 0x03c3, + 0x03a4 => 0x03c4, + 0x03a5 => 0x03c5, + 0x03a6 => 0x03c6, + 0x03a7 => 0x03c7, + 0x03a8 => 0x03c8, + 0x03a9 => 0x03c9, + 0x03aa => 0x03ca, + 0x03ab => 0x03cb, + 0x03b0 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0301}',), + 0x03c2 => 0x03c3, + 0x03cf => 0x03d7, + 0x03d0 => 0x03b2, + 0x03d1 => 0x03b8, + 0x03d5 => 0x03c6, + 0x03d6 => 0x03c0, + 0x03d8 => 0x03d9, + 0x03da => 0x03db, + 0x03dc => 0x03dd, + 0x03de => 0x03df, + 0x03e0 => 0x03e1, + 0x03e2 => 0x03e3, + 0x03e4 => 0x03e5, + 0x03e6 => 0x03e7, + 0x03e8 => 0x03e9, + 0x03ea => 0x03eb, + 0x03ec => 0x03ed, + 0x03ee => 0x03ef, + 0x03f0 => 0x03ba, + 0x03f1 => 0x03c1, + 0x03f4 => 0x03b8, + 0x03f5 => 0x03b5, + 0x03f7 => 0x03f8, + 0x03f9 => 0x03f2, + 0x03fa => 0x03fb, + 0x03fd => 0x037b, + 0x03fe => 0x037c, + 0x03ff => 0x037d, + 0x0400 => 0x0450, + 0x0401 => 0x0451, + 0x0402 => 0x0452, + 0x0403 => 0x0453, + 0x0404 => 0x0454, + 0x0405 => 0x0455, + 0x0406 => 0x0456, + 0x0407 => 0x0457, + 0x0408 => 0x0458, + 0x0409 => 0x0459, + 0x040a => 0x045a, + 0x040b => 0x045b, + 0x040c => 0x045c, + 0x040d => 0x045d, + 0x040e => 0x045e, + 0x040f => 0x045f, + 0x0410 => 0x0430, + 0x0411 => 0x0431, + 0x0412 => 0x0432, + 0x0413 => 0x0433, + 0x0414 => 0x0434, + 0x0415 => 0x0435, + 0x0416 => 0x0436, + 0x0417 => 0x0437, + 0x0418 => 0x0438, + 0x0419 => 0x0439, + 0x041a => 0x043a, + 0x041b => 0x043b, + 0x041c => 0x043c, + 0x041d => 0x043d, + 0x041e => 0x043e, + 0x041f => 0x043f, + 0x0420 => 0x0440, + 0x0421 => 0x0441, + 0x0422 => 0x0442, + 0x0423 => 0x0443, + 0x0424 => 0x0444, + 0x0425 => 0x0445, + 0x0426 => 0x0446, + 0x0427 => 0x0447, + 0x0428 => 0x0448, + 0x0429 => 0x0449, + 0x042a => 0x044a, + 0x042b => 0x044b, + 0x042c => 0x044c, + 0x042d => 0x044d, + 0x042e => 0x044e, + 0x042f => 0x044f, + 0x0460 => 0x0461, + 0x0462 => 0x0463, + 0x0464 => 0x0465, + 0x0466 => 0x0467, + 0x0468 => 0x0469, + 0x046a => 0x046b, + 0x046c => 0x046d, + 0x046e => 0x046f, + 0x0470 => 0x0471, + 0x0472 => 0x0473, + 0x0474 => 0x0475, + 0x0476 => 0x0477, + 0x0478 => 0x0479, + 0x047a => 0x047b, + 0x047c => 0x047d, + 0x047e => 0x047f, + 0x0480 => 0x0481, + 0x048a => 0x048b, + 0x048c => 0x048d, + 0x048e => 0x048f, + 0x0490 => 0x0491, + 0x0492 => 0x0493, + 0x0494 => 0x0495, + 0x0496 => 0x0497, + 0x0498 => 0x0499, + 0x049a => 0x049b, + 0x049c => 0x049d, + 0x049e => 0x049f, + 0x04a0 => 0x04a1, + 0x04a2 => 0x04a3, + 0x04a4 => 0x04a5, + 0x04a6 => 0x04a7, + 0x04a8 => 0x04a9, + 0x04aa => 0x04ab, + 0x04ac => 0x04ad, + 0x04ae => 0x04af, + 0x04b0 => 0x04b1, + 0x04b2 => 0x04b3, + 0x04b4 => 0x04b5, + 0x04b6 => 0x04b7, + 0x04b8 => 0x04b9, + 0x04ba => 0x04bb, + 0x04bc => 0x04bd, + 0x04be => 0x04bf, + 0x04c0 => 0x04cf, + 0x04c1 => 0x04c2, + 0x04c3 => 0x04c4, + 0x04c5 => 0x04c6, + 0x04c7 => 0x04c8, + 0x04c9 => 0x04ca, + 0x04cb => 0x04cc, + 0x04cd => 0x04ce, + 0x04d0 => 0x04d1, + 0x04d2 => 0x04d3, + 0x04d4 => 0x04d5, + 0x04d6 => 0x04d7, + 0x04d8 => 0x04d9, + 0x04da => 0x04db, + 0x04dc => 0x04dd, + 0x04de => 0x04df, + 0x04e0 => 0x04e1, + 0x04e2 => 0x04e3, + 0x04e4 => 0x04e5, + 0x04e6 => 0x04e7, + 0x04e8 => 0x04e9, + 0x04ea => 0x04eb, + 0x04ec => 0x04ed, + 0x04ee => 0x04ef, + 0x04f0 => 0x04f1, + 0x04f2 => 0x04f3, + 0x04f4 => 0x04f5, + 0x04f6 => 0x04f7, + 0x04f8 => 0x04f9, + 0x04fa => 0x04fb, + 0x04fc => 0x04fd, + 0x04fe => 0x04ff, + 0x0500 => 0x0501, + 0x0502 => 0x0503, + 0x0504 => 0x0505, + 0x0506 => 0x0507, + 0x0508 => 0x0509, + 0x050a => 0x050b, + 0x050c => 0x050d, + 0x050e => 0x050f, + 0x0510 => 0x0511, + 0x0512 => 0x0513, + 0x0514 => 0x0515, + 0x0516 => 0x0517, + 0x0518 => 0x0519, + 0x051a => 0x051b, + 0x051c => 0x051d, + 0x051e => 0x051f, + 0x0520 => 0x0521, + 0x0522 => 0x0523, + 0x0524 => 0x0525, + 0x0526 => 0x0527, + 0x0528 => 0x0529, + 0x052a => 0x052b, + 0x052c => 0x052d, + 0x052e => 0x052f, + 0x0531 => 0x0561, + 0x0532 => 0x0562, + 0x0533 => 0x0563, + 0x0534 => 0x0564, + 0x0535 => 0x0565, + 0x0536 => 0x0566, + 0x0537 => 0x0567, + 0x0538 => 0x0568, + 0x0539 => 0x0569, + 0x053a => 0x056a, + 0x053b => 0x056b, + 0x053c => 0x056c, + 0x053d => 0x056d, + 0x053e => 0x056e, + 0x053f => 0x056f, + 0x0540 => 0x0570, + 0x0541 => 0x0571, + 0x0542 => 0x0572, + 0x0543 => 0x0573, + 0x0544 => 0x0574, + 0x0545 => 0x0575, + 0x0546 => 0x0576, + 0x0547 => 0x0577, + 0x0548 => 0x0578, + 0x0549 => 0x0579, + 0x054a => 0x057a, + 0x054b => 0x057b, + 0x054c => 0x057c, + 0x054d => 0x057d, + 0x054e => 0x057e, + 0x054f => 0x057f, + 0x0550 => 0x0580, + 0x0551 => 0x0581, + 0x0552 => 0x0582, + 0x0553 => 0x0583, + 0x0554 => 0x0584, + 0x0555 => 0x0585, + 0x0556 => 0x0586, + 0x0587 => return Fold::Two('\u{0565}', '\u{0582}',), + 0x10a0 => 0x2d00, + 0x10a1 => 0x2d01, + 0x10a2 => 0x2d02, + 0x10a3 => 0x2d03, + 0x10a4 => 0x2d04, + 0x10a5 => 0x2d05, + 0x10a6 => 0x2d06, + 0x10a7 => 0x2d07, + 0x10a8 => 0x2d08, + 0x10a9 => 0x2d09, + 0x10aa => 0x2d0a, + 0x10ab => 0x2d0b, + 0x10ac => 0x2d0c, + 0x10ad => 0x2d0d, + 0x10ae => 0x2d0e, + 0x10af => 0x2d0f, + 0x10b0 => 0x2d10, + 0x10b1 => 0x2d11, + 0x10b2 => 0x2d12, + 0x10b3 => 0x2d13, + 0x10b4 => 0x2d14, + 0x10b5 => 0x2d15, + 0x10b6 => 0x2d16, + 0x10b7 => 0x2d17, + 0x10b8 => 0x2d18, + 0x10b9 => 0x2d19, + 0x10ba => 0x2d1a, + 0x10bb => 0x2d1b, + 0x10bc => 0x2d1c, + 0x10bd => 0x2d1d, + 0x10be => 0x2d1e, + 0x10bf => 0x2d1f, + 0x10c0 => 0x2d20, + 0x10c1 => 0x2d21, + 0x10c2 => 0x2d22, + 0x10c3 => 0x2d23, + 0x10c4 => 0x2d24, + 0x10c5 => 0x2d25, + 0x10c7 => 0x2d27, + 0x10cd => 0x2d2d, + 0x13f8 => 0x13f0, + 0x13f9 => 0x13f1, + 0x13fa => 0x13f2, + 0x13fb => 0x13f3, + 0x13fc => 0x13f4, + 0x13fd => 0x13f5, + 0x1c80 => 0x0432, + 0x1c81 => 0x0434, + 0x1c82 => 0x043e, + 0x1c83 => 0x0441, + 0x1c84 => 0x0442, + 0x1c85 => 0x0442, + 0x1c86 => 0x044a, + 0x1c87 => 0x0463, + 0x1c88 => 0xa64b, + 0x1c90 => 0x10d0, + 0x1c91 => 0x10d1, + 0x1c92 => 0x10d2, + 0x1c93 => 0x10d3, + 0x1c94 => 0x10d4, + 0x1c95 => 0x10d5, + 0x1c96 => 0x10d6, + 0x1c97 => 0x10d7, + 0x1c98 => 0x10d8, + 0x1c99 => 0x10d9, + 0x1c9a => 0x10da, + 0x1c9b => 0x10db, + 0x1c9c => 0x10dc, + 0x1c9d => 0x10dd, + 0x1c9e => 0x10de, + 0x1c9f => 0x10df, + 0x1ca0 => 0x10e0, + 0x1ca1 => 0x10e1, + 0x1ca2 => 0x10e2, + 0x1ca3 => 0x10e3, + 0x1ca4 => 0x10e4, + 0x1ca5 => 0x10e5, + 0x1ca6 => 0x10e6, + 0x1ca7 => 0x10e7, + 0x1ca8 => 0x10e8, + 0x1ca9 => 0x10e9, + 0x1caa => 0x10ea, + 0x1cab => 0x10eb, + 0x1cac => 0x10ec, + 0x1cad => 0x10ed, + 0x1cae => 0x10ee, + 0x1caf => 0x10ef, + 0x1cb0 => 0x10f0, + 0x1cb1 => 0x10f1, + 0x1cb2 => 0x10f2, + 0x1cb3 => 0x10f3, + 0x1cb4 => 0x10f4, + 0x1cb5 => 0x10f5, + 0x1cb6 => 0x10f6, + 0x1cb7 => 0x10f7, + 0x1cb8 => 0x10f8, + 0x1cb9 => 0x10f9, + 0x1cba => 0x10fa, + 0x1cbd => 0x10fd, + 0x1cbe => 0x10fe, + 0x1cbf => 0x10ff, + 0x1e00 => 0x1e01, + 0x1e02 => 0x1e03, + 0x1e04 => 0x1e05, + 0x1e06 => 0x1e07, + 0x1e08 => 0x1e09, + 0x1e0a => 0x1e0b, + 0x1e0c => 0x1e0d, + 0x1e0e => 0x1e0f, + 0x1e10 => 0x1e11, + 0x1e12 => 0x1e13, + 0x1e14 => 0x1e15, + 0x1e16 => 0x1e17, + 0x1e18 => 0x1e19, + 0x1e1a => 0x1e1b, + 0x1e1c => 0x1e1d, + 0x1e1e => 0x1e1f, + 0x1e20 => 0x1e21, + 0x1e22 => 0x1e23, + 0x1e24 => 0x1e25, + 0x1e26 => 0x1e27, + 0x1e28 => 0x1e29, + 0x1e2a => 0x1e2b, + 0x1e2c => 0x1e2d, + 0x1e2e => 0x1e2f, + 0x1e30 => 0x1e31, + 0x1e32 => 0x1e33, + 0x1e34 => 0x1e35, + 0x1e36 => 0x1e37, + 0x1e38 => 0x1e39, + 0x1e3a => 0x1e3b, + 0x1e3c => 0x1e3d, + 0x1e3e => 0x1e3f, + 0x1e40 => 0x1e41, + 0x1e42 => 0x1e43, + 0x1e44 => 0x1e45, + 0x1e46 => 0x1e47, + 0x1e48 => 0x1e49, + 0x1e4a => 0x1e4b, + 0x1e4c => 0x1e4d, + 0x1e4e => 0x1e4f, + 0x1e50 => 0x1e51, + 0x1e52 => 0x1e53, + 0x1e54 => 0x1e55, + 0x1e56 => 0x1e57, + 0x1e58 => 0x1e59, + 0x1e5a => 0x1e5b, + 0x1e5c => 0x1e5d, + 0x1e5e => 0x1e5f, + 0x1e60 => 0x1e61, + 0x1e62 => 0x1e63, + 0x1e64 => 0x1e65, + 0x1e66 => 0x1e67, + 0x1e68 => 0x1e69, + 0x1e6a => 0x1e6b, + 0x1e6c => 0x1e6d, + 0x1e6e => 0x1e6f, + 0x1e70 => 0x1e71, + 0x1e72 => 0x1e73, + 0x1e74 => 0x1e75, + 0x1e76 => 0x1e77, + 0x1e78 => 0x1e79, + 0x1e7a => 0x1e7b, + 0x1e7c => 0x1e7d, + 0x1e7e => 0x1e7f, + 0x1e80 => 0x1e81, + 0x1e82 => 0x1e83, + 0x1e84 => 0x1e85, + 0x1e86 => 0x1e87, + 0x1e88 => 0x1e89, + 0x1e8a => 0x1e8b, + 0x1e8c => 0x1e8d, + 0x1e8e => 0x1e8f, + 0x1e90 => 0x1e91, + 0x1e92 => 0x1e93, + 0x1e94 => 0x1e95, + 0x1e96 => return Fold::Two('\u{0068}', '\u{0331}',), + 0x1e97 => return Fold::Two('\u{0074}', '\u{0308}',), + 0x1e98 => return Fold::Two('\u{0077}', '\u{030a}',), + 0x1e99 => return Fold::Two('\u{0079}', '\u{030a}',), + 0x1e9a => return Fold::Two('\u{0061}', '\u{02be}',), + 0x1e9b => 0x1e61, + 0x1e9e => return Fold::Two('\u{0073}', '\u{0073}',), + 0x1ea0 => 0x1ea1, + 0x1ea2 => 0x1ea3, + 0x1ea4 => 0x1ea5, + 0x1ea6 => 0x1ea7, + 0x1ea8 => 0x1ea9, + 0x1eaa => 0x1eab, + 0x1eac => 0x1ead, + 0x1eae => 0x1eaf, + 0x1eb0 => 0x1eb1, + 0x1eb2 => 0x1eb3, + 0x1eb4 => 0x1eb5, + 0x1eb6 => 0x1eb7, + 0x1eb8 => 0x1eb9, + 0x1eba => 0x1ebb, + 0x1ebc => 0x1ebd, + 0x1ebe => 0x1ebf, + 0x1ec0 => 0x1ec1, + 0x1ec2 => 0x1ec3, + 0x1ec4 => 0x1ec5, + 0x1ec6 => 0x1ec7, + 0x1ec8 => 0x1ec9, + 0x1eca => 0x1ecb, + 0x1ecc => 0x1ecd, + 0x1ece => 0x1ecf, + 0x1ed0 => 0x1ed1, + 0x1ed2 => 0x1ed3, + 0x1ed4 => 0x1ed5, + 0x1ed6 => 0x1ed7, + 0x1ed8 => 0x1ed9, + 0x1eda => 0x1edb, + 0x1edc => 0x1edd, + 0x1ede => 0x1edf, + 0x1ee0 => 0x1ee1, + 0x1ee2 => 0x1ee3, + 0x1ee4 => 0x1ee5, + 0x1ee6 => 0x1ee7, + 0x1ee8 => 0x1ee9, + 0x1eea => 0x1eeb, + 0x1eec => 0x1eed, + 0x1eee => 0x1eef, + 0x1ef0 => 0x1ef1, + 0x1ef2 => 0x1ef3, + 0x1ef4 => 0x1ef5, + 0x1ef6 => 0x1ef7, + 0x1ef8 => 0x1ef9, + 0x1efa => 0x1efb, + 0x1efc => 0x1efd, + 0x1efe => 0x1eff, + 0x1f08 => 0x1f00, + 0x1f09 => 0x1f01, + 0x1f0a => 0x1f02, + 0x1f0b => 0x1f03, + 0x1f0c => 0x1f04, + 0x1f0d => 0x1f05, + 0x1f0e => 0x1f06, + 0x1f0f => 0x1f07, + 0x1f18 => 0x1f10, + 0x1f19 => 0x1f11, + 0x1f1a => 0x1f12, + 0x1f1b => 0x1f13, + 0x1f1c => 0x1f14, + 0x1f1d => 0x1f15, + 0x1f28 => 0x1f20, + 0x1f29 => 0x1f21, + 0x1f2a => 0x1f22, + 0x1f2b => 0x1f23, + 0x1f2c => 0x1f24, + 0x1f2d => 0x1f25, + 0x1f2e => 0x1f26, + 0x1f2f => 0x1f27, + 0x1f38 => 0x1f30, + 0x1f39 => 0x1f31, + 0x1f3a => 0x1f32, + 0x1f3b => 0x1f33, + 0x1f3c => 0x1f34, + 0x1f3d => 0x1f35, + 0x1f3e => 0x1f36, + 0x1f3f => 0x1f37, + 0x1f48 => 0x1f40, + 0x1f49 => 0x1f41, + 0x1f4a => 0x1f42, + 0x1f4b => 0x1f43, + 0x1f4c => 0x1f44, + 0x1f4d => 0x1f45, + 0x1f50 => return Fold::Two('\u{03c5}', '\u{0313}',), + 0x1f52 => return Fold::Three('\u{03c5}', '\u{0313}', '\u{0300}',), + 0x1f54 => return Fold::Three('\u{03c5}', '\u{0313}', '\u{0301}',), + 0x1f56 => return Fold::Three('\u{03c5}', '\u{0313}', '\u{0342}',), + 0x1f59 => 0x1f51, + 0x1f5b => 0x1f53, + 0x1f5d => 0x1f55, + 0x1f5f => 0x1f57, + 0x1f68 => 0x1f60, + 0x1f69 => 0x1f61, + 0x1f6a => 0x1f62, + 0x1f6b => 0x1f63, + 0x1f6c => 0x1f64, + 0x1f6d => 0x1f65, + 0x1f6e => 0x1f66, + 0x1f6f => 0x1f67, + 0x1f80 => return Fold::Two('\u{1f00}', '\u{03b9}',), + 0x1f81 => return Fold::Two('\u{1f01}', '\u{03b9}',), + 0x1f82 => return Fold::Two('\u{1f02}', '\u{03b9}',), + 0x1f83 => return Fold::Two('\u{1f03}', '\u{03b9}',), + 0x1f84 => return Fold::Two('\u{1f04}', '\u{03b9}',), + 0x1f85 => return Fold::Two('\u{1f05}', '\u{03b9}',), + 0x1f86 => return Fold::Two('\u{1f06}', '\u{03b9}',), + 0x1f87 => return Fold::Two('\u{1f07}', '\u{03b9}',), + 0x1f88 => return Fold::Two('\u{1f00}', '\u{03b9}',), + 0x1f89 => return Fold::Two('\u{1f01}', '\u{03b9}',), + 0x1f8a => return Fold::Two('\u{1f02}', '\u{03b9}',), + 0x1f8b => return Fold::Two('\u{1f03}', '\u{03b9}',), + 0x1f8c => return Fold::Two('\u{1f04}', '\u{03b9}',), + 0x1f8d => return Fold::Two('\u{1f05}', '\u{03b9}',), + 0x1f8e => return Fold::Two('\u{1f06}', '\u{03b9}',), + 0x1f8f => return Fold::Two('\u{1f07}', '\u{03b9}',), + 0x1f90 => return Fold::Two('\u{1f20}', '\u{03b9}',), + 0x1f91 => return Fold::Two('\u{1f21}', '\u{03b9}',), + 0x1f92 => return Fold::Two('\u{1f22}', '\u{03b9}',), + 0x1f93 => return Fold::Two('\u{1f23}', '\u{03b9}',), + 0x1f94 => return Fold::Two('\u{1f24}', '\u{03b9}',), + 0x1f95 => return Fold::Two('\u{1f25}', '\u{03b9}',), + 0x1f96 => return Fold::Two('\u{1f26}', '\u{03b9}',), + 0x1f97 => return Fold::Two('\u{1f27}', '\u{03b9}',), + 0x1f98 => return Fold::Two('\u{1f20}', '\u{03b9}',), + 0x1f99 => return Fold::Two('\u{1f21}', '\u{03b9}',), + 0x1f9a => return Fold::Two('\u{1f22}', '\u{03b9}',), + 0x1f9b => return Fold::Two('\u{1f23}', '\u{03b9}',), + 0x1f9c => return Fold::Two('\u{1f24}', '\u{03b9}',), + 0x1f9d => return Fold::Two('\u{1f25}', '\u{03b9}',), + 0x1f9e => return Fold::Two('\u{1f26}', '\u{03b9}',), + 0x1f9f => return Fold::Two('\u{1f27}', '\u{03b9}',), + 0x1fa0 => return Fold::Two('\u{1f60}', '\u{03b9}',), + 0x1fa1 => return Fold::Two('\u{1f61}', '\u{03b9}',), + 0x1fa2 => return Fold::Two('\u{1f62}', '\u{03b9}',), + 0x1fa3 => return Fold::Two('\u{1f63}', '\u{03b9}',), + 0x1fa4 => return Fold::Two('\u{1f64}', '\u{03b9}',), + 0x1fa5 => return Fold::Two('\u{1f65}', '\u{03b9}',), + 0x1fa6 => return Fold::Two('\u{1f66}', '\u{03b9}',), + 0x1fa7 => return Fold::Two('\u{1f67}', '\u{03b9}',), + 0x1fa8 => return Fold::Two('\u{1f60}', '\u{03b9}',), + 0x1fa9 => return Fold::Two('\u{1f61}', '\u{03b9}',), + 0x1faa => return Fold::Two('\u{1f62}', '\u{03b9}',), + 0x1fab => return Fold::Two('\u{1f63}', '\u{03b9}',), + 0x1fac => return Fold::Two('\u{1f64}', '\u{03b9}',), + 0x1fad => return Fold::Two('\u{1f65}', '\u{03b9}',), + 0x1fae => return Fold::Two('\u{1f66}', '\u{03b9}',), + 0x1faf => return Fold::Two('\u{1f67}', '\u{03b9}',), + 0x1fb2 => return Fold::Two('\u{1f70}', '\u{03b9}',), + 0x1fb3 => return Fold::Two('\u{03b1}', '\u{03b9}',), + 0x1fb4 => return Fold::Two('\u{03ac}', '\u{03b9}',), + 0x1fb6 => return Fold::Two('\u{03b1}', '\u{0342}',), + 0x1fb7 => return Fold::Three('\u{03b1}', '\u{0342}', '\u{03b9}',), + 0x1fb8 => 0x1fb0, + 0x1fb9 => 0x1fb1, + 0x1fba => 0x1f70, + 0x1fbb => 0x1f71, + 0x1fbc => return Fold::Two('\u{03b1}', '\u{03b9}',), + 0x1fbe => 0x03b9, + 0x1fc2 => return Fold::Two('\u{1f74}', '\u{03b9}',), + 0x1fc3 => return Fold::Two('\u{03b7}', '\u{03b9}',), + 0x1fc4 => return Fold::Two('\u{03ae}', '\u{03b9}',), + 0x1fc6 => return Fold::Two('\u{03b7}', '\u{0342}',), + 0x1fc7 => return Fold::Three('\u{03b7}', '\u{0342}', '\u{03b9}',), + 0x1fc8 => 0x1f72, + 0x1fc9 => 0x1f73, + 0x1fca => 0x1f74, + 0x1fcb => 0x1f75, + 0x1fcc => return Fold::Two('\u{03b7}', '\u{03b9}',), + 0x1fd2 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0300}',), + 0x1fd3 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0301}',), + 0x1fd6 => return Fold::Two('\u{03b9}', '\u{0342}',), + 0x1fd7 => return Fold::Three('\u{03b9}', '\u{0308}', '\u{0342}',), + 0x1fd8 => 0x1fd0, + 0x1fd9 => 0x1fd1, + 0x1fda => 0x1f76, + 0x1fdb => 0x1f77, + 0x1fe2 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0300}',), + 0x1fe3 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0301}',), + 0x1fe4 => return Fold::Two('\u{03c1}', '\u{0313}',), + 0x1fe6 => return Fold::Two('\u{03c5}', '\u{0342}',), + 0x1fe7 => return Fold::Three('\u{03c5}', '\u{0308}', '\u{0342}',), + 0x1fe8 => 0x1fe0, + 0x1fe9 => 0x1fe1, + 0x1fea => 0x1f7a, + 0x1feb => 0x1f7b, + 0x1fec => 0x1fe5, + 0x1ff2 => return Fold::Two('\u{1f7c}', '\u{03b9}',), + 0x1ff3 => return Fold::Two('\u{03c9}', '\u{03b9}',), + 0x1ff4 => return Fold::Two('\u{03ce}', '\u{03b9}',), + 0x1ff6 => return Fold::Two('\u{03c9}', '\u{0342}',), + 0x1ff7 => return Fold::Three('\u{03c9}', '\u{0342}', '\u{03b9}',), + 0x1ff8 => 0x1f78, + 0x1ff9 => 0x1f79, + 0x1ffa => 0x1f7c, + 0x1ffb => 0x1f7d, + 0x1ffc => return Fold::Two('\u{03c9}', '\u{03b9}',), + 0x2126 => 0x03c9, + 0x212a => 0x006b, + 0x212b => 0x00e5, + 0x2132 => 0x214e, + 0x2160 => 0x2170, + 0x2161 => 0x2171, + 0x2162 => 0x2172, + 0x2163 => 0x2173, + 0x2164 => 0x2174, + 0x2165 => 0x2175, + 0x2166 => 0x2176, + 0x2167 => 0x2177, + 0x2168 => 0x2178, + 0x2169 => 0x2179, + 0x216a => 0x217a, + 0x216b => 0x217b, + 0x216c => 0x217c, + 0x216d => 0x217d, + 0x216e => 0x217e, + 0x216f => 0x217f, + 0x2183 => 0x2184, + 0x24b6 => 0x24d0, + 0x24b7 => 0x24d1, + 0x24b8 => 0x24d2, + 0x24b9 => 0x24d3, + 0x24ba => 0x24d4, + 0x24bb => 0x24d5, + 0x24bc => 0x24d6, + 0x24bd => 0x24d7, + 0x24be => 0x24d8, + 0x24bf => 0x24d9, + 0x24c0 => 0x24da, + 0x24c1 => 0x24db, + 0x24c2 => 0x24dc, + 0x24c3 => 0x24dd, + 0x24c4 => 0x24de, + 0x24c5 => 0x24df, + 0x24c6 => 0x24e0, + 0x24c7 => 0x24e1, + 0x24c8 => 0x24e2, + 0x24c9 => 0x24e3, + 0x24ca => 0x24e4, + 0x24cb => 0x24e5, + 0x24cc => 0x24e6, + 0x24cd => 0x24e7, + 0x24ce => 0x24e8, + 0x24cf => 0x24e9, + 0x2c00 => 0x2c30, + 0x2c01 => 0x2c31, + 0x2c02 => 0x2c32, + 0x2c03 => 0x2c33, + 0x2c04 => 0x2c34, + 0x2c05 => 0x2c35, + 0x2c06 => 0x2c36, + 0x2c07 => 0x2c37, + 0x2c08 => 0x2c38, + 0x2c09 => 0x2c39, + 0x2c0a => 0x2c3a, + 0x2c0b => 0x2c3b, + 0x2c0c => 0x2c3c, + 0x2c0d => 0x2c3d, + 0x2c0e => 0x2c3e, + 0x2c0f => 0x2c3f, + 0x2c10 => 0x2c40, + 0x2c11 => 0x2c41, + 0x2c12 => 0x2c42, + 0x2c13 => 0x2c43, + 0x2c14 => 0x2c44, + 0x2c15 => 0x2c45, + 0x2c16 => 0x2c46, + 0x2c17 => 0x2c47, + 0x2c18 => 0x2c48, + 0x2c19 => 0x2c49, + 0x2c1a => 0x2c4a, + 0x2c1b => 0x2c4b, + 0x2c1c => 0x2c4c, + 0x2c1d => 0x2c4d, + 0x2c1e => 0x2c4e, + 0x2c1f => 0x2c4f, + 0x2c20 => 0x2c50, + 0x2c21 => 0x2c51, + 0x2c22 => 0x2c52, + 0x2c23 => 0x2c53, + 0x2c24 => 0x2c54, + 0x2c25 => 0x2c55, + 0x2c26 => 0x2c56, + 0x2c27 => 0x2c57, + 0x2c28 => 0x2c58, + 0x2c29 => 0x2c59, + 0x2c2a => 0x2c5a, + 0x2c2b => 0x2c5b, + 0x2c2c => 0x2c5c, + 0x2c2d => 0x2c5d, + 0x2c2e => 0x2c5e, + 0x2c60 => 0x2c61, + 0x2c62 => 0x026b, + 0x2c63 => 0x1d7d, + 0x2c64 => 0x027d, + 0x2c67 => 0x2c68, + 0x2c69 => 0x2c6a, + 0x2c6b => 0x2c6c, + 0x2c6d => 0x0251, + 0x2c6e => 0x0271, + 0x2c6f => 0x0250, + 0x2c70 => 0x0252, + 0x2c72 => 0x2c73, + 0x2c75 => 0x2c76, + 0x2c7e => 0x023f, + 0x2c7f => 0x0240, + 0x2c80 => 0x2c81, + 0x2c82 => 0x2c83, + 0x2c84 => 0x2c85, + 0x2c86 => 0x2c87, + 0x2c88 => 0x2c89, + 0x2c8a => 0x2c8b, + 0x2c8c => 0x2c8d, + 0x2c8e => 0x2c8f, + 0x2c90 => 0x2c91, + 0x2c92 => 0x2c93, + 0x2c94 => 0x2c95, + 0x2c96 => 0x2c97, + 0x2c98 => 0x2c99, + 0x2c9a => 0x2c9b, + 0x2c9c => 0x2c9d, + 0x2c9e => 0x2c9f, + 0x2ca0 => 0x2ca1, + 0x2ca2 => 0x2ca3, + 0x2ca4 => 0x2ca5, + 0x2ca6 => 0x2ca7, + 0x2ca8 => 0x2ca9, + 0x2caa => 0x2cab, + 0x2cac => 0x2cad, + 0x2cae => 0x2caf, + 0x2cb0 => 0x2cb1, + 0x2cb2 => 0x2cb3, + 0x2cb4 => 0x2cb5, + 0x2cb6 => 0x2cb7, + 0x2cb8 => 0x2cb9, + 0x2cba => 0x2cbb, + 0x2cbc => 0x2cbd, + 0x2cbe => 0x2cbf, + 0x2cc0 => 0x2cc1, + 0x2cc2 => 0x2cc3, + 0x2cc4 => 0x2cc5, + 0x2cc6 => 0x2cc7, + 0x2cc8 => 0x2cc9, + 0x2cca => 0x2ccb, + 0x2ccc => 0x2ccd, + 0x2cce => 0x2ccf, + 0x2cd0 => 0x2cd1, + 0x2cd2 => 0x2cd3, + 0x2cd4 => 0x2cd5, + 0x2cd6 => 0x2cd7, + 0x2cd8 => 0x2cd9, + 0x2cda => 0x2cdb, + 0x2cdc => 0x2cdd, + 0x2cde => 0x2cdf, + 0x2ce0 => 0x2ce1, + 0x2ce2 => 0x2ce3, + 0x2ceb => 0x2cec, + 0x2ced => 0x2cee, + 0x2cf2 => 0x2cf3, + 0xa640 => 0xa641, + 0xa642 => 0xa643, + 0xa644 => 0xa645, + 0xa646 => 0xa647, + 0xa648 => 0xa649, + 0xa64a => 0xa64b, + 0xa64c => 0xa64d, + 0xa64e => 0xa64f, + 0xa650 => 0xa651, + 0xa652 => 0xa653, + 0xa654 => 0xa655, + 0xa656 => 0xa657, + 0xa658 => 0xa659, + 0xa65a => 0xa65b, + 0xa65c => 0xa65d, + 0xa65e => 0xa65f, + 0xa660 => 0xa661, + 0xa662 => 0xa663, + 0xa664 => 0xa665, + 0xa666 => 0xa667, + 0xa668 => 0xa669, + 0xa66a => 0xa66b, + 0xa66c => 0xa66d, + 0xa680 => 0xa681, + 0xa682 => 0xa683, + 0xa684 => 0xa685, + 0xa686 => 0xa687, + 0xa688 => 0xa689, + 0xa68a => 0xa68b, + 0xa68c => 0xa68d, + 0xa68e => 0xa68f, + 0xa690 => 0xa691, + 0xa692 => 0xa693, + 0xa694 => 0xa695, + 0xa696 => 0xa697, + 0xa698 => 0xa699, + 0xa69a => 0xa69b, + 0xa722 => 0xa723, + 0xa724 => 0xa725, + 0xa726 => 0xa727, + 0xa728 => 0xa729, + 0xa72a => 0xa72b, + 0xa72c => 0xa72d, + 0xa72e => 0xa72f, + 0xa732 => 0xa733, + 0xa734 => 0xa735, + 0xa736 => 0xa737, + 0xa738 => 0xa739, + 0xa73a => 0xa73b, + 0xa73c => 0xa73d, + 0xa73e => 0xa73f, + 0xa740 => 0xa741, + 0xa742 => 0xa743, + 0xa744 => 0xa745, + 0xa746 => 0xa747, + 0xa748 => 0xa749, + 0xa74a => 0xa74b, + 0xa74c => 0xa74d, + 0xa74e => 0xa74f, + 0xa750 => 0xa751, + 0xa752 => 0xa753, + 0xa754 => 0xa755, + 0xa756 => 0xa757, + 0xa758 => 0xa759, + 0xa75a => 0xa75b, + 0xa75c => 0xa75d, + 0xa75e => 0xa75f, + 0xa760 => 0xa761, + 0xa762 => 0xa763, + 0xa764 => 0xa765, + 0xa766 => 0xa767, + 0xa768 => 0xa769, + 0xa76a => 0xa76b, + 0xa76c => 0xa76d, + 0xa76e => 0xa76f, + 0xa779 => 0xa77a, + 0xa77b => 0xa77c, + 0xa77d => 0x1d79, + 0xa77e => 0xa77f, + 0xa780 => 0xa781, + 0xa782 => 0xa783, + 0xa784 => 0xa785, + 0xa786 => 0xa787, + 0xa78b => 0xa78c, + 0xa78d => 0x0265, + 0xa790 => 0xa791, + 0xa792 => 0xa793, + 0xa796 => 0xa797, + 0xa798 => 0xa799, + 0xa79a => 0xa79b, + 0xa79c => 0xa79d, + 0xa79e => 0xa79f, + 0xa7a0 => 0xa7a1, + 0xa7a2 => 0xa7a3, + 0xa7a4 => 0xa7a5, + 0xa7a6 => 0xa7a7, + 0xa7a8 => 0xa7a9, + 0xa7aa => 0x0266, + 0xa7ab => 0x025c, + 0xa7ac => 0x0261, + 0xa7ad => 0x026c, + 0xa7ae => 0x026a, + 0xa7b0 => 0x029e, + 0xa7b1 => 0x0287, + 0xa7b2 => 0x029d, + 0xa7b3 => 0xab53, + 0xa7b4 => 0xa7b5, + 0xa7b6 => 0xa7b7, + 0xa7b8 => 0xa7b9, + 0xa7ba => 0xa7bb, + 0xa7bc => 0xa7bd, + 0xa7be => 0xa7bf, + 0xa7c2 => 0xa7c3, + 0xa7c4 => 0xa794, + 0xa7c5 => 0x0282, + 0xa7c6 => 0x1d8e, + 0xab70 => 0x13a0, + 0xab71 => 0x13a1, + 0xab72 => 0x13a2, + 0xab73 => 0x13a3, + 0xab74 => 0x13a4, + 0xab75 => 0x13a5, + 0xab76 => 0x13a6, + 0xab77 => 0x13a7, + 0xab78 => 0x13a8, + 0xab79 => 0x13a9, + 0xab7a => 0x13aa, + 0xab7b => 0x13ab, + 0xab7c => 0x13ac, + 0xab7d => 0x13ad, + 0xab7e => 0x13ae, + 0xab7f => 0x13af, + 0xab80 => 0x13b0, + 0xab81 => 0x13b1, + 0xab82 => 0x13b2, + 0xab83 => 0x13b3, + 0xab84 => 0x13b4, + 0xab85 => 0x13b5, + 0xab86 => 0x13b6, + 0xab87 => 0x13b7, + 0xab88 => 0x13b8, + 0xab89 => 0x13b9, + 0xab8a => 0x13ba, + 0xab8b => 0x13bb, + 0xab8c => 0x13bc, + 0xab8d => 0x13bd, + 0xab8e => 0x13be, + 0xab8f => 0x13bf, + 0xab90 => 0x13c0, + 0xab91 => 0x13c1, + 0xab92 => 0x13c2, + 0xab93 => 0x13c3, + 0xab94 => 0x13c4, + 0xab95 => 0x13c5, + 0xab96 => 0x13c6, + 0xab97 => 0x13c7, + 0xab98 => 0x13c8, + 0xab99 => 0x13c9, + 0xab9a => 0x13ca, + 0xab9b => 0x13cb, + 0xab9c => 0x13cc, + 0xab9d => 0x13cd, + 0xab9e => 0x13ce, + 0xab9f => 0x13cf, + 0xaba0 => 0x13d0, + 0xaba1 => 0x13d1, + 0xaba2 => 0x13d2, + 0xaba3 => 0x13d3, + 0xaba4 => 0x13d4, + 0xaba5 => 0x13d5, + 0xaba6 => 0x13d6, + 0xaba7 => 0x13d7, + 0xaba8 => 0x13d8, + 0xaba9 => 0x13d9, + 0xabaa => 0x13da, + 0xabab => 0x13db, + 0xabac => 0x13dc, + 0xabad => 0x13dd, + 0xabae => 0x13de, + 0xabaf => 0x13df, + 0xabb0 => 0x13e0, + 0xabb1 => 0x13e1, + 0xabb2 => 0x13e2, + 0xabb3 => 0x13e3, + 0xabb4 => 0x13e4, + 0xabb5 => 0x13e5, + 0xabb6 => 0x13e6, + 0xabb7 => 0x13e7, + 0xabb8 => 0x13e8, + 0xabb9 => 0x13e9, + 0xabba => 0x13ea, + 0xabbb => 0x13eb, + 0xabbc => 0x13ec, + 0xabbd => 0x13ed, + 0xabbe => 0x13ee, + 0xabbf => 0x13ef, + 0xfb00 => return Fold::Two('\u{0066}', '\u{0066}',), + 0xfb01 => return Fold::Two('\u{0066}', '\u{0069}',), + 0xfb02 => return Fold::Two('\u{0066}', '\u{006c}',), + 0xfb03 => return Fold::Three('\u{0066}', '\u{0066}', '\u{0069}',), + 0xfb04 => return Fold::Three('\u{0066}', '\u{0066}', '\u{006c}',), + 0xfb05 => return Fold::Two('\u{0073}', '\u{0074}',), + 0xfb06 => return Fold::Two('\u{0073}', '\u{0074}',), + 0xfb13 => return Fold::Two('\u{0574}', '\u{0576}',), + 0xfb14 => return Fold::Two('\u{0574}', '\u{0565}',), + 0xfb15 => return Fold::Two('\u{0574}', '\u{056b}',), + 0xfb16 => return Fold::Two('\u{057e}', '\u{0576}',), + 0xfb17 => return Fold::Two('\u{0574}', '\u{056d}',), + 0xff21 => 0xff41, + 0xff22 => 0xff42, + 0xff23 => 0xff43, + 0xff24 => 0xff44, + 0xff25 => 0xff45, + 0xff26 => 0xff46, + 0xff27 => 0xff47, + 0xff28 => 0xff48, + 0xff29 => 0xff49, + 0xff2a => 0xff4a, + 0xff2b => 0xff4b, + 0xff2c => 0xff4c, + 0xff2d => 0xff4d, + 0xff2e => 0xff4e, + 0xff2f => 0xff4f, + 0xff30 => 0xff50, + 0xff31 => 0xff51, + 0xff32 => 0xff52, + 0xff33 => 0xff53, + 0xff34 => 0xff54, + 0xff35 => 0xff55, + 0xff36 => 0xff56, + 0xff37 => 0xff57, + 0xff38 => 0xff58, + 0xff39 => 0xff59, + 0xff3a => 0xff5a, + 0x10400 => 0x10428, + 0x10401 => 0x10429, + 0x10402 => 0x1042a, + 0x10403 => 0x1042b, + 0x10404 => 0x1042c, + 0x10405 => 0x1042d, + 0x10406 => 0x1042e, + 0x10407 => 0x1042f, + 0x10408 => 0x10430, + 0x10409 => 0x10431, + 0x1040a => 0x10432, + 0x1040b => 0x10433, + 0x1040c => 0x10434, + 0x1040d => 0x10435, + 0x1040e => 0x10436, + 0x1040f => 0x10437, + 0x10410 => 0x10438, + 0x10411 => 0x10439, + 0x10412 => 0x1043a, + 0x10413 => 0x1043b, + 0x10414 => 0x1043c, + 0x10415 => 0x1043d, + 0x10416 => 0x1043e, + 0x10417 => 0x1043f, + 0x10418 => 0x10440, + 0x10419 => 0x10441, + 0x1041a => 0x10442, + 0x1041b => 0x10443, + 0x1041c => 0x10444, + 0x1041d => 0x10445, + 0x1041e => 0x10446, + 0x1041f => 0x10447, + 0x10420 => 0x10448, + 0x10421 => 0x10449, + 0x10422 => 0x1044a, + 0x10423 => 0x1044b, + 0x10424 => 0x1044c, + 0x10425 => 0x1044d, + 0x10426 => 0x1044e, + 0x10427 => 0x1044f, + 0x104b0 => 0x104d8, + 0x104b1 => 0x104d9, + 0x104b2 => 0x104da, + 0x104b3 => 0x104db, + 0x104b4 => 0x104dc, + 0x104b5 => 0x104dd, + 0x104b6 => 0x104de, + 0x104b7 => 0x104df, + 0x104b8 => 0x104e0, + 0x104b9 => 0x104e1, + 0x104ba => 0x104e2, + 0x104bb => 0x104e3, + 0x104bc => 0x104e4, + 0x104bd => 0x104e5, + 0x104be => 0x104e6, + 0x104bf => 0x104e7, + 0x104c0 => 0x104e8, + 0x104c1 => 0x104e9, + 0x104c2 => 0x104ea, + 0x104c3 => 0x104eb, + 0x104c4 => 0x104ec, + 0x104c5 => 0x104ed, + 0x104c6 => 0x104ee, + 0x104c7 => 0x104ef, + 0x104c8 => 0x104f0, + 0x104c9 => 0x104f1, + 0x104ca => 0x104f2, + 0x104cb => 0x104f3, + 0x104cc => 0x104f4, + 0x104cd => 0x104f5, + 0x104ce => 0x104f6, + 0x104cf => 0x104f7, + 0x104d0 => 0x104f8, + 0x104d1 => 0x104f9, + 0x104d2 => 0x104fa, + 0x104d3 => 0x104fb, + 0x10c80 => 0x10cc0, + 0x10c81 => 0x10cc1, + 0x10c82 => 0x10cc2, + 0x10c83 => 0x10cc3, + 0x10c84 => 0x10cc4, + 0x10c85 => 0x10cc5, + 0x10c86 => 0x10cc6, + 0x10c87 => 0x10cc7, + 0x10c88 => 0x10cc8, + 0x10c89 => 0x10cc9, + 0x10c8a => 0x10cca, + 0x10c8b => 0x10ccb, + 0x10c8c => 0x10ccc, + 0x10c8d => 0x10ccd, + 0x10c8e => 0x10cce, + 0x10c8f => 0x10ccf, + 0x10c90 => 0x10cd0, + 0x10c91 => 0x10cd1, + 0x10c92 => 0x10cd2, + 0x10c93 => 0x10cd3, + 0x10c94 => 0x10cd4, + 0x10c95 => 0x10cd5, + 0x10c96 => 0x10cd6, + 0x10c97 => 0x10cd7, + 0x10c98 => 0x10cd8, + 0x10c99 => 0x10cd9, + 0x10c9a => 0x10cda, + 0x10c9b => 0x10cdb, + 0x10c9c => 0x10cdc, + 0x10c9d => 0x10cdd, + 0x10c9e => 0x10cde, + 0x10c9f => 0x10cdf, + 0x10ca0 => 0x10ce0, + 0x10ca1 => 0x10ce1, + 0x10ca2 => 0x10ce2, + 0x10ca3 => 0x10ce3, + 0x10ca4 => 0x10ce4, + 0x10ca5 => 0x10ce5, + 0x10ca6 => 0x10ce6, + 0x10ca7 => 0x10ce7, + 0x10ca8 => 0x10ce8, + 0x10ca9 => 0x10ce9, + 0x10caa => 0x10cea, + 0x10cab => 0x10ceb, + 0x10cac => 0x10cec, + 0x10cad => 0x10ced, + 0x10cae => 0x10cee, + 0x10caf => 0x10cef, + 0x10cb0 => 0x10cf0, + 0x10cb1 => 0x10cf1, + 0x10cb2 => 0x10cf2, + 0x118a0 => 0x118c0, + 0x118a1 => 0x118c1, + 0x118a2 => 0x118c2, + 0x118a3 => 0x118c3, + 0x118a4 => 0x118c4, + 0x118a5 => 0x118c5, + 0x118a6 => 0x118c6, + 0x118a7 => 0x118c7, + 0x118a8 => 0x118c8, + 0x118a9 => 0x118c9, + 0x118aa => 0x118ca, + 0x118ab => 0x118cb, + 0x118ac => 0x118cc, + 0x118ad => 0x118cd, + 0x118ae => 0x118ce, + 0x118af => 0x118cf, + 0x118b0 => 0x118d0, + 0x118b1 => 0x118d1, + 0x118b2 => 0x118d2, + 0x118b3 => 0x118d3, + 0x118b4 => 0x118d4, + 0x118b5 => 0x118d5, + 0x118b6 => 0x118d6, + 0x118b7 => 0x118d7, + 0x118b8 => 0x118d8, + 0x118b9 => 0x118d9, + 0x118ba => 0x118da, + 0x118bb => 0x118db, + 0x118bc => 0x118dc, + 0x118bd => 0x118dd, + 0x118be => 0x118de, + 0x118bf => 0x118df, + 0x16e40 => 0x16e60, + 0x16e41 => 0x16e61, + 0x16e42 => 0x16e62, + 0x16e43 => 0x16e63, + 0x16e44 => 0x16e64, + 0x16e45 => 0x16e65, + 0x16e46 => 0x16e66, + 0x16e47 => 0x16e67, + 0x16e48 => 0x16e68, + 0x16e49 => 0x16e69, + 0x16e4a => 0x16e6a, + 0x16e4b => 0x16e6b, + 0x16e4c => 0x16e6c, + 0x16e4d => 0x16e6d, + 0x16e4e => 0x16e6e, + 0x16e4f => 0x16e6f, + 0x16e50 => 0x16e70, + 0x16e51 => 0x16e71, + 0x16e52 => 0x16e72, + 0x16e53 => 0x16e73, + 0x16e54 => 0x16e74, + 0x16e55 => 0x16e75, + 0x16e56 => 0x16e76, + 0x16e57 => 0x16e77, + 0x16e58 => 0x16e78, + 0x16e59 => 0x16e79, + 0x16e5a => 0x16e7a, + 0x16e5b => 0x16e7b, + 0x16e5c => 0x16e7c, + 0x16e5d => 0x16e7d, + 0x16e5e => 0x16e7e, + 0x16e5f => 0x16e7f, + 0x1e900 => 0x1e922, + 0x1e901 => 0x1e923, + 0x1e902 => 0x1e924, + 0x1e903 => 0x1e925, + 0x1e904 => 0x1e926, + 0x1e905 => 0x1e927, + 0x1e906 => 0x1e928, + 0x1e907 => 0x1e929, + 0x1e908 => 0x1e92a, + 0x1e909 => 0x1e92b, + 0x1e90a => 0x1e92c, + 0x1e90b => 0x1e92d, + 0x1e90c => 0x1e92e, + 0x1e90d => 0x1e92f, + 0x1e90e => 0x1e930, + 0x1e90f => 0x1e931, + 0x1e910 => 0x1e932, + 0x1e911 => 0x1e933, + 0x1e912 => 0x1e934, + 0x1e913 => 0x1e935, + 0x1e914 => 0x1e936, + 0x1e915 => 0x1e937, + 0x1e916 => 0x1e938, + 0x1e917 => 0x1e939, + 0x1e918 => 0x1e93a, + 0x1e919 => 0x1e93b, + 0x1e91a => 0x1e93c, + 0x1e91b => 0x1e93d, + 0x1e91c => 0x1e93e, + 0x1e91d => 0x1e93f, + 0x1e91e => 0x1e940, + 0x1e91f => 0x1e941, + 0x1e920 => 0x1e942, + 0x1e921 => 0x1e943, + _ => orig as u32 + }; + Fold::One( char::from_u32(single_char).unwrap() ) + } + + for c_index in 0..126217 { + if let Some(c) = char::from_u32(c_index) { + let reference: Vec<char> = lookup_naive(c).collect(); + let actual: Vec<char> = lookup(c).collect(); + if actual != reference { + assert!(false, "case-folding {:?} (#0x{:04x}) failed: Expected {:?}, got {:?}", c, c_index, reference, actual); + } + } + } +} diff --git a/third_party/rust/unicase/src/unicode/mod.rs b/third_party/rust/unicase/src/unicode/mod.rs new file mode 100644 index 0000000000..8b887331bf --- /dev/null +++ b/third_party/rust/unicase/src/unicode/mod.rs @@ -0,0 +1,201 @@ +#[cfg(__unicase__iter_cmp)] +use core::cmp::Ordering; +use core::hash::{Hash, Hasher}; + +use self::map::lookup; +mod map; + +#[derive(Clone, Copy, Debug, Default)] +pub struct Unicode<S>(pub S); + +impl<S1: AsRef<str>, S2: AsRef<str>> PartialEq<Unicode<S2>> for Unicode<S1> { + #[inline] + fn eq(&self, other: &Unicode<S2>) -> bool { + let mut left = self.0.as_ref().chars().flat_map(lookup); + let mut right = other.0.as_ref().chars().flat_map(lookup); + + // inline Iterator::eq since not added until Rust 1.5 + loop { + let x = match left.next() { + None => return right.next().is_none(), + Some(val) => val, + }; + + let y = match right.next() { + None => return false, + Some(val) => val, + }; + + if x != y { + return false; + } + } + } +} + +impl<S: AsRef<str>> Eq for Unicode<S> {} + +#[cfg(__unicase__iter_cmp)] +impl<T: AsRef<str>> PartialOrd for Unicode<T> { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +#[cfg(__unicase__iter_cmp)] +impl<T: AsRef<str>> Ord for Unicode<T> { + #[inline] + fn cmp(&self, other: &Self) -> Ordering { + let self_chars = self.0.as_ref().chars().flat_map(lookup); + let other_chars = other.0.as_ref().chars().flat_map(lookup); + self_chars.cmp(other_chars) + } +} + +impl<S: AsRef<str>> Hash for Unicode<S> { + #[inline] + fn hash<H: Hasher>(&self, hasher: &mut H) { + let mut buf = [0; 4]; + for c in self.0.as_ref().chars().flat_map(|c| lookup(c)) { + let len = char_to_utf8(c, &mut buf); + hasher.write(&buf[..len]) + } + } +} + +#[inline] +fn char_to_utf8(c: char, dst: &mut [u8; 4]) -> usize { + const TAG_CONT: u8 = 0b1000_0000; + const TAG_TWO_B: u8 = 0b1100_0000; + const TAG_THREE_B: u8 = 0b1110_0000; + const TAG_FOUR_B: u8 = 0b1111_0000; + + let code = c as u32; + if code <= 0x7F { + dst[0] = code as u8; + 1 + } else if code <= 0x7FF { + dst[0] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; + dst[1] = (code & 0x3F) as u8 | TAG_CONT; + 2 + } else if code <= 0xFFFF { + dst[0] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; + dst[1] = (code >> 6 & 0x3F) as u8 | TAG_CONT; + dst[2] = (code & 0x3F) as u8 | TAG_CONT; + 3 + } else { + dst[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; + dst[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT; + dst[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT; + dst[3] = (code & 0x3F) as u8 | TAG_CONT; + 4 + } +} + +// internal mod so that the enum can be 'pub' +// thanks privacy-checker :___( +mod fold { + #[derive(Clone, Copy)] + pub enum Fold { + Zero, + One(char), + Two(char, char), + Three(char, char, char), + } + + impl Iterator for Fold { + type Item = char; + #[inline] + fn next(&mut self) -> Option<char> { + match *self { + Fold::Zero => None, + Fold::One(one) => { + *self = Fold::Zero; + Some(one) + }, + Fold::Two(one, two) => { + *self = Fold::One(two); + Some(one) + }, + Fold::Three(one, two, three) => { + *self = Fold::Two(one, two); + Some(three) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + match *self { + Fold::Zero => (0, Some(0)), + Fold::One(..) => (1, Some(1)), + Fold::Two(..) => (2, Some(2)), + Fold::Three(..) => (3, Some(3)) + } + } + + } + impl From<(char,)> for Fold { + #[inline] + fn from((one,): (char,)) -> Fold { + Fold::One(one) + } + } + + impl From<(char, char)> for Fold { + #[inline] + fn from((one, two): (char, char)) -> Fold { + Fold::Two(one, two) + } + } + + impl From<(char, char, char)> for Fold { + #[inline] + fn from((one, two, three): (char, char, char)) -> Fold { + Fold::Three(one, two, three) + } + } +} + +#[cfg(test)] +mod tests { + use super::Unicode; + + macro_rules! eq { + ($left:expr, $right:expr) => ({ + assert_eq!(Unicode($left), Unicode($right)); + }); + } + + #[test] + fn test_ascii_folding() { + eq!("foo bar", "FoO BAR"); + } + + #[test] + fn test_simple_case_folding() { + eq!("στιγμας", "στιγμασ"); + } + + #[test] + fn test_full_case_folding() { + eq!("flour", "flour"); + eq!("Maße", "MASSE"); + eq!("ᾲ στο διάολο", "ὰι στο διάολο"); + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_ascii_folding(b: &mut ::test::Bencher) { + b.bytes = b"foo bar".len() as u64; + b.iter(|| eq!("foo bar", "FoO BAR")); + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_simple_case_folding(b: &mut ::test::Bencher) { + b.bytes = "στιγμας".len() as u64; + b.iter(|| eq!("στιγμας", "στιγμασ")); + } +} |