Skip to main content

core/unicode/
unicode_data.rs

1//! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!
2// Alphabetic      :  1723 bytes, 147369 codepoints in 759 ranges (U+0000AA - U+03347A) using skiplist
3// Case_Ignorable  :  1063 bytes,   2789 codepoints in 459 ranges (U+0000A8 - U+0E01F0) using skiplist
4// Cased           :   401 bytes,   4580 codepoints in 156 ranges (U+0000AA - U+01F18A) using skiplist
5// Grapheme_Extend :   899 bytes,   2232 codepoints in 383 ranges (U+000300 - U+0E01F0) using skiplist
6// Lowercase       :   943 bytes,   2569 codepoints in 676 ranges (U+0000AA - U+01E944) using bitset
7// N               :   463 bytes,   1914 codepoints in 145 ranges (U+0000B2 - U+01FBFA) using skiplist
8// Uppercase       :   799 bytes,   1980 codepoints in 659 ranges (U+0000C0 - U+01F18A) using bitset
9// White_Space     :   256 bytes,     19 codepoints in   8 ranges (U+000085 - U+003001) using cascading
10// to_lower        :  1112 bytes,   1462 codepoints in 185 ranges (U+0000C0 - U+01E921) using 2-level LUT
11// to_upper        :  1998 bytes,   1554 codepoints in 299 ranges (U+0000B5 - U+01E943) using 2-level LUT
12// to_title        :   340 bytes,    135 codepoints in  49 ranges (U+0000DF - U+00FB17) using 2-level LUT
13// Total           :  9997 bytes
14
15#[inline(always)]
16const fn bitset_search<
17    const N: usize,
18    const CHUNK_SIZE: usize,
19    const N1: usize,
20    const CANONICAL: usize,
21    const CANONICALIZED: usize,
22>(
23    needle: u32,
24    chunk_idx_map: &[u8; N],
25    bitset_chunk_idx: &[[u8; CHUNK_SIZE]; N1],
26    bitset_canonical: &[u64; CANONICAL],
27    bitset_canonicalized: &[(u8, u8); CANONICALIZED],
28) -> bool {
29    let bucket_idx = (needle / 64) as usize;
30    let chunk_map_idx = bucket_idx / CHUNK_SIZE;
31    let chunk_piece = bucket_idx % CHUNK_SIZE;
32    // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const.
33    let chunk_idx = if chunk_map_idx < chunk_idx_map.len() {
34        chunk_idx_map[chunk_map_idx]
35    } else {
36        return false;
37    };
38    let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize;
39    // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const.
40    let word = if idx < bitset_canonical.len() {
41        bitset_canonical[idx]
42    } else {
43        let (real_idx, mapping) = bitset_canonicalized[idx - bitset_canonical.len()];
44        let mut word = bitset_canonical[real_idx as usize];
45        let should_invert = mapping & (1 << 6) != 0;
46        if should_invert {
47            word = !word;
48        }
49        // Lower 6 bits
50        let quantity = mapping & ((1 << 6) - 1);
51        if mapping & (1 << 7) != 0 {
52            // shift
53            word >>= quantity as u64;
54        } else {
55            word = word.rotate_left(quantity as u32);
56        }
57        word
58    };
59    (word & (1 << (needle % 64) as u64)) != 0
60}
61
62#[repr(transparent)]
63struct ShortOffsetRunHeader(u32);
64
65impl ShortOffsetRunHeader {
66    const fn new(start_index: usize, prefix_sum: u32) -> Self {
67        assert!(start_index < (1 << 11));
68        assert!(prefix_sum < (1 << 21));
69
70        Self((start_index as u32) << 21 | prefix_sum)
71    }
72
73    #[inline]
74    const fn start_index(&self) -> usize {
75        (self.0 >> 21) as usize
76    }
77
78    #[inline]
79    const fn prefix_sum(&self) -> u32 {
80        self.0 & ((1 << 21) - 1)
81    }
82}
83
84/// # Safety
85///
86/// - The last element of `short_offset_runs` must be greater than `std::char::MAX`.
87/// - The start indices of all elements in `short_offset_runs` must be less than `OFFSETS`.
88#[inline(always)]
89unsafe fn skip_search<const SOR: usize, const OFFSETS: usize>(
90    needle: char,
91    short_offset_runs: &[ShortOffsetRunHeader; SOR],
92    offsets: &[u8; OFFSETS],
93) -> bool {
94    let needle = needle as u32;
95
96    let last_idx =
97        match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header.0 << 11) {
98            Ok(idx) => idx + 1,
99            Err(idx) => idx,
100        };
101    // SAFETY: `last_idx` *cannot* be past the end of the array, as the last
102    // element is greater than `std::char::MAX` (the largest possible needle)
103    // as guaranteed by the caller.
104    //
105    // So, we cannot have found it (i.e. `Ok(idx) => idx + 1 != length`) and the
106    // correct location cannot be past it, so `Err(idx) => idx != length` either.
107    //
108    // This means that we can avoid bounds checking for the accesses below, too.
109    //
110    // We need to use `intrinsics::assume` since the `panic_nounwind` contained
111    // in `hint::assert_unchecked` may not be optimized out.
112    unsafe { crate::intrinsics::assume(last_idx < SOR) };
113
114    let mut offset_idx = short_offset_runs[last_idx].start_index();
115    let length = if let Some(next) = short_offset_runs.get(last_idx + 1) {
116        (*next).start_index() - offset_idx
117    } else {
118        offsets.len() - offset_idx
119    };
120
121    let prev =
122        last_idx.checked_sub(1).map(|prev| short_offset_runs[prev].prefix_sum()).unwrap_or(0);
123
124    let total = needle - prev;
125    let mut prefix_sum = 0;
126    for _ in 0..(length - 1) {
127        // SAFETY: It is guaranteed that `length <= OFFSETS - offset_idx`,
128        // so it follows that `length - 1 + offset_idx < OFFSETS`, therefore
129        // `offset_idx < OFFSETS` is always true in this loop.
130        //
131        // We need to use `intrinsics::assume` since the `panic_nounwind` contained
132        // in `hint::assert_unchecked` may not be optimized out.
133        unsafe { crate::intrinsics::assume(offset_idx < OFFSETS) };
134        let offset = offsets[offset_idx];
135        prefix_sum += offset as u32;
136        if prefix_sum > total {
137            break;
138        }
139        offset_idx += 1;
140    }
141    offset_idx % 2 == 1
142}
143
144pub const UNICODE_VERSION: (u8, u8, u8) = (17, 0, 0);
145
146#[rustfmt::skip]
147pub mod alphabetic {
148    use super::ShortOffsetRunHeader;
149
150    static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 51] = [
151        ShortOffsetRunHeader::new(0, 706), ShortOffsetRunHeader::new(12, 4681),
152        ShortOffsetRunHeader::new(414, 5741), ShortOffsetRunHeader::new(452, 7958),
153        ShortOffsetRunHeader::new(552, 9398), ShortOffsetRunHeader::new(623, 11264),
154        ShortOffsetRunHeader::new(625, 12293), ShortOffsetRunHeader::new(663, 13312),
155        ShortOffsetRunHeader::new(687, 19904), ShortOffsetRunHeader::new(688, 42125),
156        ShortOffsetRunHeader::new(690, 42509), ShortOffsetRunHeader::new(694, 55204),
157        ShortOffsetRunHeader::new(778, 63744), ShortOffsetRunHeader::new(783, 64110),
158        ShortOffsetRunHeader::new(784, 64830), ShortOffsetRunHeader::new(806, 66176),
159        ShortOffsetRunHeader::new(847, 67383), ShortOffsetRunHeader::new(894, 73440),
160        ShortOffsetRunHeader::new(1217, 74650), ShortOffsetRunHeader::new(1228, 77712),
161        ShortOffsetRunHeader::new(1233, 78896), ShortOffsetRunHeader::new(1236, 82939),
162        ShortOffsetRunHeader::new(1240, 83527), ShortOffsetRunHeader::new(1242, 90368),
163        ShortOffsetRunHeader::new(1243, 92160), ShortOffsetRunHeader::new(1245, 92729),
164        ShortOffsetRunHeader::new(1246, 93504), ShortOffsetRunHeader::new(1261, 101590),
165        ShortOffsetRunHeader::new(1282, 110576), ShortOffsetRunHeader::new(1287, 110883),
166        ShortOffsetRunHeader::new(1294, 111356), ShortOffsetRunHeader::new(1304, 113664),
167        ShortOffsetRunHeader::new(1305, 119808), ShortOffsetRunHeader::new(1315, 120486),
168        ShortOffsetRunHeader::new(1352, 122624), ShortOffsetRunHeader::new(1375, 123536),
169        ShortOffsetRunHeader::new(1399, 124112), ShortOffsetRunHeader::new(1403, 126464),
170        ShortOffsetRunHeader::new(1431, 127280), ShortOffsetRunHeader::new(1497, 131072),
171        ShortOffsetRunHeader::new(1503, 173792), ShortOffsetRunHeader::new(1504, 178206),
172        ShortOffsetRunHeader::new(1506, 183982), ShortOffsetRunHeader::new(1508, 191457),
173        ShortOffsetRunHeader::new(1510, 192094), ShortOffsetRunHeader::new(1512, 194560),
174        ShortOffsetRunHeader::new(1513, 195102), ShortOffsetRunHeader::new(1514, 196608),
175        ShortOffsetRunHeader::new(1515, 201547), ShortOffsetRunHeader::new(1516, 210042),
176        ShortOffsetRunHeader::new(1518, 1324154),
177    ];
178    static OFFSETS: [u8; 1519] = [
179        170, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 29, 18, 1, 2, 2,
180        4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39, 14, 1, 1,
181        1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10, 3, 2, 1,
182        16, 48, 13, 101, 24, 33, 9, 2, 4, 1, 5, 24, 2, 19, 19, 25, 7, 11, 5, 24, 1, 7, 7, 1, 8, 42,
183        10, 12, 3, 7, 6, 76, 1, 16, 1, 3, 4, 15, 13, 19, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, 3, 4, 3, 8,
184        2, 2, 2, 2, 1, 1, 8, 1, 4, 2, 1, 5, 12, 2, 10, 1, 4, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, 2,
185        1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1, 5,
186        3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2,
187        2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3, 12,
188        4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3, 1,
189        2, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 5, 3, 1, 4, 13, 3,
190        12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9, 1,
191        1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1, 19,
192        1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, 55, 1, 1, 2, 5,
193        16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, 33,
194        1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1, 26,
195        5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, 67, 89,
196        7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, 20, 50, 1,
197        23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10, 36, 2,
198        11, 5, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 19, 34, 11, 0, 2, 6, 2, 38, 2, 6, 2, 8, 1,
199        1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116, 1,
200        13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4, 5, 5,
201        4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, 9, 7, 1,
202        7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, 86, 6, 3,
203        1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, 2, 20, 47,
204        5, 8, 3, 113, 39, 9, 2, 103, 2, 82, 20, 21, 1, 33, 24, 52, 12, 68, 1, 1, 44, 6, 3, 1, 1, 3,
205        10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55, 9, 14, 18, 23, 3, 69, 1,
206        1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43, 1, 14, 6, 123, 21, 0, 12,
207        23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1, 1, 2, 1, 2, 1, 108, 33, 0,
208        18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3, 6, 2, 6, 2, 6, 2, 3, 35,
209        12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3, 49, 47, 32, 13, 30, 5, 43,
210        5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52, 12, 11, 1, 15, 1, 7, 1, 2,
211        1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1, 9, 69, 6, 2, 1, 1,
212        44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 6, 26, 38, 56, 6, 2, 64,
213        4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10, 19, 13, 18,
214        110, 73, 55, 51, 13, 51, 13, 40, 34, 28, 3, 1, 5, 23, 250, 42, 1, 2, 3, 2, 16, 6, 50, 3, 3,
215        29, 10, 1, 8, 22, 42, 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, 13, 25, 23, 51, 17, 4,
216        8, 35, 3, 1, 9, 64, 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 4, 62, 7, 1, 1, 1, 4,
217        1, 15, 1, 10, 7, 57, 23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, 3, 1, 6,
218        1, 5, 7, 28, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, 4, 1, 2, 3, 1, 1, 1, 44, 66, 1, 3,
219        1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, 2, 1, 71,
220        27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, 4, 93, 8,
221        2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 103, 8, 88, 33, 31, 9, 1, 45,
222        1, 7, 1, 1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, 6,
223        1, 2, 1, 37, 1, 2, 1, 4, 1, 1, 23, 44, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, 102, 111,
224        17, 196, 0, 97, 15, 0, 17, 6, 25, 0, 5, 0, 0, 47, 0, 0, 7, 31, 17, 79, 17, 30, 18, 48, 16,
225        4, 31, 21, 5, 19, 0, 45, 211, 64, 32, 25, 2, 25, 44, 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 7,
226        9, 0, 41, 32, 97, 115, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5,
227        13, 3, 9, 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4,
228        2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25,
229        1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33,
230        1, 112, 45, 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 228, 30, 2, 1, 207, 31, 1, 22, 8, 2, 224, 7,
231        1, 4, 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4,
232        1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1,
233        1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0,
234        32, 0, 2, 0, 2, 0, 15, 0, 0, 0, 0, 0, 5, 0, 0,
235    ];
236    #[inline]
237    pub fn lookup(c: char) -> bool {
238        debug_assert!(!c.is_ascii());
239        (c as u32) >= 0xaa && lookup_slow(c)
240    }
241
242    #[inline(never)]
243    fn lookup_slow(c: char) -> bool {
244        const {
245            assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
246            let mut i = 0;
247            while i < SHORT_OFFSET_RUNS.len() {
248                assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());
249                i += 1;
250            }
251        }
252        // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`
253        // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.
254        unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }
255    }
256}
257
258#[rustfmt::skip]
259pub mod case_ignorable {
260    use super::ShortOffsetRunHeader;
261
262    static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 36] = [
263        ShortOffsetRunHeader::new(0, 688), ShortOffsetRunHeader::new(11, 4957),
264        ShortOffsetRunHeader::new(263, 5906), ShortOffsetRunHeader::new(265, 8125),
265        ShortOffsetRunHeader::new(377, 11388), ShortOffsetRunHeader::new(411, 12293),
266        ShortOffsetRunHeader::new(423, 40981), ShortOffsetRunHeader::new(435, 42232),
267        ShortOffsetRunHeader::new(437, 42508), ShortOffsetRunHeader::new(439, 64286),
268        ShortOffsetRunHeader::new(535, 65024), ShortOffsetRunHeader::new(539, 66045),
269        ShortOffsetRunHeader::new(569, 67456), ShortOffsetRunHeader::new(575, 68097),
270        ShortOffsetRunHeader::new(581, 68900), ShortOffsetRunHeader::new(593, 69291),
271        ShortOffsetRunHeader::new(601, 71727), ShortOffsetRunHeader::new(727, 71995),
272        ShortOffsetRunHeader::new(731, 73459), ShortOffsetRunHeader::new(797, 78896),
273        ShortOffsetRunHeader::new(809, 90398), ShortOffsetRunHeader::new(813, 92912),
274        ShortOffsetRunHeader::new(817, 93504), ShortOffsetRunHeader::new(823, 94031),
275        ShortOffsetRunHeader::new(827, 110576), ShortOffsetRunHeader::new(837, 113821),
276        ShortOffsetRunHeader::new(843, 118528), ShortOffsetRunHeader::new(847, 119143),
277        ShortOffsetRunHeader::new(851, 121344), ShortOffsetRunHeader::new(861, 122880),
278        ShortOffsetRunHeader::new(873, 123566), ShortOffsetRunHeader::new(889, 124139),
279        ShortOffsetRunHeader::new(893, 125136), ShortOffsetRunHeader::new(907, 127995),
280        ShortOffsetRunHeader::new(911, 917505), ShortOffsetRunHeader::new(913, 2032112),
281    ];
282    static OFFSETS: [u8; 919] = [
283        168, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2, 1, 1, 251, 7, 207, 1, 5, 1, 49,
284        45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35, 1, 10, 21, 16, 1, 101, 8, 1, 10,
285        1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24, 24, 43, 3, 44, 1, 7, 2, 5, 9, 41,
286        58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1, 58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2,
287        2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6,
288        1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1, 61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3,
289        5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1, 5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1,
290        20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9, 98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1,
291        1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1, 102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3,
292        16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3, 29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1,
293        2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118, 3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58,
294        1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 46, 2, 12, 20, 4, 48, 1, 1, 5, 1, 1, 5, 1,
295        40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3, 58, 8, 2, 2, 64, 6, 82, 3, 1, 13,
296        1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1, 3, 11, 3, 13, 3, 13, 3, 13, 2, 12,
297        5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1, 16, 13, 51, 33, 0, 2, 113, 3, 125, 1,
298        15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6, 93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10,
299        1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 102, 4, 3, 2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151,
300        2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4, 2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2,
301        12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2, 1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5,
302        9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3, 1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6,
303        1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3, 0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9,
304        0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 38, 1, 26, 5, 1, 1, 0, 2, 24, 1, 52, 6, 70, 11,
305        49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, 50, 3, 36, 5, 1,
306        8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57,
307        2, 3, 1, 37, 7, 3, 5, 70, 6, 13, 1, 1, 1, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1,
308        1, 4, 2, 1, 2, 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101,
309        1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4,
310        8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 198, 1, 1, 3, 1, 1, 201, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2,
311        1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 65, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1,
312        1, 23, 1, 0, 17, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 9, 4, 0, 3, 40, 2, 0, 1, 63, 17, 64, 2, 1,
313        2, 13, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0,
314        55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160, 14,
315        0, 1, 61, 4, 0, 5, 254, 2, 243, 1, 2, 1, 7, 2, 5, 1, 9, 1, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96,
316        128, 240, 0,
317    ];
318    #[inline]
319    pub fn lookup(c: char) -> bool {
320        debug_assert!(!c.is_ascii());
321        (c as u32) >= 0xa8 && lookup_slow(c)
322    }
323
324    #[inline(never)]
325    fn lookup_slow(c: char) -> bool {
326        const {
327            assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
328            let mut i = 0;
329            while i < SHORT_OFFSET_RUNS.len() {
330                assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());
331                i += 1;
332            }
333        }
334        // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`
335        // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.
336        unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }
337    }
338}
339
340#[rustfmt::skip]
341pub mod cased {
342    use super::ShortOffsetRunHeader;
343
344    static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 22] = [
345        ShortOffsetRunHeader::new(0, 4256), ShortOffsetRunHeader::new(51, 5024),
346        ShortOffsetRunHeader::new(61, 7296), ShortOffsetRunHeader::new(65, 7958),
347        ShortOffsetRunHeader::new(74, 9398), ShortOffsetRunHeader::new(149, 11264),
348        ShortOffsetRunHeader::new(151, 42560), ShortOffsetRunHeader::new(163, 43824),
349        ShortOffsetRunHeader::new(177, 64256), ShortOffsetRunHeader::new(183, 65313),
350        ShortOffsetRunHeader::new(187, 66560), ShortOffsetRunHeader::new(191, 67456),
351        ShortOffsetRunHeader::new(213, 68736), ShortOffsetRunHeader::new(221, 71840),
352        ShortOffsetRunHeader::new(229, 93760), ShortOffsetRunHeader::new(231, 119808),
353        ShortOffsetRunHeader::new(237, 120486), ShortOffsetRunHeader::new(274, 122624),
354        ShortOffsetRunHeader::new(297, 122928), ShortOffsetRunHeader::new(303, 125184),
355        ShortOffsetRunHeader::new(305, 127280), ShortOffsetRunHeader::new(307, 1241482),
356    ];
357    static OFFSETS: [u8; 313] = [
358        170, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 2, 35, 7, 2, 30, 5, 96, 1, 42, 4,
359        2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9, 41, 0, 38, 1, 1,
360        5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 11, 5, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2, 38, 2, 6, 2, 8,
361        1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7, 116,
362        1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 6, 4, 1, 2, 4,
363        5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 0, 46, 18, 30, 132,
364        102, 3, 4, 1, 77, 20, 6, 1, 3, 0, 43, 1, 14, 6, 80, 0, 7, 12, 5, 0, 26, 6, 26, 0, 80, 96,
365        36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0,
366        51, 13, 51, 93, 22, 10, 22, 0, 64, 0, 64, 32, 25, 2, 25, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2,
367        4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25,
368        1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6, 0,
369        62, 0, 68, 0, 26, 6, 26, 6, 26, 0,
370    ];
371    #[inline]
372    pub fn lookup(c: char) -> bool {
373        debug_assert!(!c.is_ascii());
374        (c as u32) >= 0xaa && lookup_slow(c)
375    }
376
377    #[inline(never)]
378    fn lookup_slow(c: char) -> bool {
379        const {
380            assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
381            let mut i = 0;
382            while i < SHORT_OFFSET_RUNS.len() {
383                assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());
384                i += 1;
385            }
386        }
387        // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`
388        // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.
389        unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }
390    }
391}
392
393#[rustfmt::skip]
394pub mod grapheme_extend {
395    use super::ShortOffsetRunHeader;
396
397    static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 33] = [
398        ShortOffsetRunHeader::new(0, 768), ShortOffsetRunHeader::new(1, 1155),
399        ShortOffsetRunHeader::new(3, 1425), ShortOffsetRunHeader::new(5, 4957),
400        ShortOffsetRunHeader::new(249, 5906), ShortOffsetRunHeader::new(251, 8204),
401        ShortOffsetRunHeader::new(347, 11503), ShortOffsetRunHeader::new(351, 12330),
402        ShortOffsetRunHeader::new(357, 42607), ShortOffsetRunHeader::new(361, 43010),
403        ShortOffsetRunHeader::new(369, 64286), ShortOffsetRunHeader::new(435, 65024),
404        ShortOffsetRunHeader::new(437, 65438), ShortOffsetRunHeader::new(441, 66045),
405        ShortOffsetRunHeader::new(443, 68097), ShortOffsetRunHeader::new(449, 68900),
406        ShortOffsetRunHeader::new(461, 69291), ShortOffsetRunHeader::new(465, 71727),
407        ShortOffsetRunHeader::new(601, 73459), ShortOffsetRunHeader::new(669, 78912),
408        ShortOffsetRunHeader::new(679, 90398), ShortOffsetRunHeader::new(683, 92912),
409        ShortOffsetRunHeader::new(687, 94031), ShortOffsetRunHeader::new(691, 113821),
410        ShortOffsetRunHeader::new(699, 118528), ShortOffsetRunHeader::new(701, 119141),
411        ShortOffsetRunHeader::new(705, 121344), ShortOffsetRunHeader::new(717, 122880),
412        ShortOffsetRunHeader::new(729, 123566), ShortOffsetRunHeader::new(743, 124140),
413        ShortOffsetRunHeader::new(747, 125136), ShortOffsetRunHeader::new(759, 917536),
414        ShortOffsetRunHeader::new(763, 2032112),
415    ];
416    static OFFSETS: [u8; 767] = [
417        0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1,
418        4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 59, 9, 42, 24, 1, 32,
419        55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2,
420        2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2, 57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6,
421        1, 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1,
422        55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 2, 1, 1, 3, 3, 1, 4, 7, 2, 11, 2, 28,
423        2, 57, 2, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7,
424        12, 8, 98, 1, 2, 9, 11, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
425        102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 4, 28, 3,
426        29, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9,
427        1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 46, 2, 12, 20, 4, 48,
428        10, 4, 3, 38, 9, 12, 2, 32, 4, 2, 6, 56, 1, 1, 2, 3, 1, 1, 5, 56, 8, 2, 2, 152, 3, 1, 13, 1,
429        7, 4, 1, 6, 1, 3, 2, 198, 64, 0, 1, 195, 33, 0, 3, 141, 1, 96, 32, 0, 6, 105, 2, 0, 4, 1,
430        10, 32, 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 1, 1,
431        44, 3, 48, 1, 2, 4, 2, 2, 2, 1, 36, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3,
432        2, 2, 5, 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1,
433        149, 5, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 65, 5, 0, 2, 77, 6, 70, 11, 49, 4, 123,
434        1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9,
435        1, 1, 8, 4, 2, 1, 95, 3, 2, 4, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 12, 1, 9,
436        1, 14, 7, 3, 5, 67, 1, 2, 6, 1, 1, 2, 1, 1, 3, 4, 3, 1, 1, 14, 2, 85, 8, 2, 3, 1, 1, 23, 1,
437        81, 1, 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2,
438        106, 1, 1, 1, 2, 8, 101, 1, 1, 1, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 4, 4, 1, 144, 4, 2, 2,
439        4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 198, 1, 1, 3, 1, 1, 201, 7, 1, 6,
440        1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 11,
441        2, 52, 5, 5, 3, 23, 1, 0, 1, 6, 15, 0, 12, 3, 3, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 11, 2, 0,
442        2, 0, 46, 2, 23, 0, 5, 3, 6, 8, 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1,
443        15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 254, 2, 243, 1, 2, 1,
444        7, 2, 5, 1, 0, 7, 109, 7, 0, 96, 128, 240, 0,
445    ];
446    #[inline]
447    pub fn lookup(c: char) -> bool {
448        debug_assert!(!c.is_ascii());
449        (c as u32) >= 0x300 && lookup_slow(c)
450    }
451
452    #[inline(never)]
453    fn lookup_slow(c: char) -> bool {
454        const {
455            assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
456            let mut i = 0;
457            while i < SHORT_OFFSET_RUNS.len() {
458                assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());
459                i += 1;
460            }
461        }
462        // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`
463        // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.
464        unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }
465    }
466}
467
468#[rustfmt::skip]
469pub mod lowercase {
470    static BITSET_CHUNKS_MAP: [u8; 123] = [
471        12, 17, 0, 0, 9, 0, 0, 13, 14, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
472        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
473        0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
474        0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0,
475        3, 18, 0, 7,
476    ];
477    static BITSET_INDEX_CHUNKS: [[u8; 16]; 20] = [
478        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
479        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0],
480        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 57, 0],
481        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0],
482        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0],
483        [0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 19, 62, 0, 0, 0, 0],
484        [0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 44, 0, 53, 49, 51, 34],
485        [0, 0, 0, 0, 9, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
486        [0, 0, 0, 3, 0, 16, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0],
487        [0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28],
488        [0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
489        [0, 0, 0, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
490        [0, 0, 35, 17, 24, 54, 55, 50, 48, 7, 36, 43, 0, 29, 12, 32],
491        [0, 0, 47, 0, 57, 57, 57, 0, 23, 23, 71, 23, 37, 26, 25, 38],
492        [0, 5, 72, 0, 30, 15, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0],
493        [10, 61, 0, 6, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 33, 0],
494        [16, 27, 23, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
495        [16, 52, 2, 22, 70, 8, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0],
496        [16, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
497        [67, 42, 56, 11, 68, 65, 18, 13, 1, 66, 78, 21, 75, 76, 4, 46],
498    ];
499    static BITSET_CANONICAL: [u64; 57] = [
500        0b0000000000000000000000000000000000000000000000000000000000000000,
501        0b0000111111111111111111111111110000000000000000000000000011111111,
502        0b1010101010101010101010101010101010101010101010101010100000000010,
503        0b0000000000000111111111111111111111111111111111111111111111111111,
504        0b1111111111111111111111000000000000000000000000001111110111111111,
505        0b1000000000000010000000000000000000000000000000000000000000000000,
506        0b0000111111111111111111111111111111111111000000000000000000000000,
507        0b1111111111111111111111111111111111111111111111111010101010000101,
508        0b1111111111111111111111111111111100000000000000000000000000000000,
509        0b1111111111111111111111111111110000000000000000000000000000000000,
510        0b1111111111111111111111110000000000000000000000000000000000000000,
511        0b1111111111111111111111000000000000000000000000001111111111101111,
512        0b1111111111111111111100000000000000000000000000010000000000000000,
513        0b1111111111111111110000000000000000000000000011111111111111111111,
514        0b1111111111111111000000111111111111110111111111111111111111111111,
515        0b1111111111111111000000000000000000000000000000000100001111000000,
516        0b1111111111111111000000000000000000000000000000000000000000000000,
517        0b1111111101111111111111111111111110000000000000000000000000000000,
518        0b1111110000000000000000000000000011111111111111111111111111000000,
519        0b1111100000000000000000000000000000000000000000000000000000000000,
520        0b1111011111111111111111111111111111111111111111110000000000000000,
521        0b1111000000000000000000000000001111110111111111111111111111111100,
522        0b1010101010101010101010101010101010101010101010101101010101010100,
523        0b1010101010101010101010101010101010101010101010101010101010101010,
524        0b0101010110101010101010101010101010101010101010101010101010101010,
525        0b0100000011011111000000001111111100000000111111110000000011111111,
526        0b0011111111111111000000001111111100000000111111110000000000111111,
527        0b0011111111011010000101010110001011111111111111111111111111111111,
528        0b0011111100000000000000000000000000000000000000000000000000000000,
529        0b0011110010001010000000000000000000000000000000000000000000100000,
530        0b0011001000010000100000000000000000000000000010001100010000000000,
531        0b0001101111111011111111111111101111111111100000000000000000000000,
532        0b0001100100101111101010101010101010101010111000110111111111111111,
533        0b0000011111111101111111111111111111111111111111111111111110111001,
534        0b0000011101011110000000000000000000001010101010101010010100001010,
535        0b0000010000100000000001000000000000000000000000000000000000000000,
536        0b0000000111111111111111111111111111111111110011111111111111111111,
537        0b0000000011111111000000001111111100000000001111110000000011111111,
538        0b0000000011011100000000001111111100000000110011110000000011011100,
539        0b0000000000001000010100000001101010101010101010101010101010101010,
540        0b0000000000000000001000001011111111111111111111111111111111111111,
541        0b0000000000000000000001111110000001111111111111111111101111111111,
542        0b0000000000000000000000001111111111111111110111111100000000000000,
543        0b0000000000000000000000000001111100000000000000000000000000000011,
544        0b0000000000000000000000000000000000111010101010101010101010101010,
545        0b0000000000000000000000000000000000000000111110000000000001111111,
546        0b0000000000000000000000000000000000000000000000000000101111110111,
547        0b0000000000000000000000000000000000000000000000000000010111111111,
548        0b1001001111111010101010101010101010101010101010101010101010101010,
549        0b1001010111111111101010101010101010101010101010101010101010101010,
550        0b1010101000101001101010101010101010110101010101010101001001000000,
551        0b1010101010100000100000101010101010101010101110100101000010101010,
552        0b1010101010101010101010101010101011111111111111111111111111111111,
553        0b1010101010101011101010101010100000000000000000000000000000000000,
554        0b1101010010101010101010101010101010101010101010101010101101010101,
555        0b1110011001010001001011010010101001001110001001000011000100101001,
556        0b1110101111000000000000000000000000001111111111111111111111111100,
557    ];
558    static BITSET_MAPPING: [(u8, u8); 22] = [
559        (0, 64), (1, 184), (1, 182), (1, 179), (1, 172), (1, 168), (1, 161), (1, 146), (1, 144),
560        (1, 140), (1, 136), (1, 132), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133),
561        (4, 12), (4, 6), (5, 187), (6, 78),
562    ];
563
564    pub const fn lookup(c: char) -> bool {
565        debug_assert!(!c.is_ascii());
566        (c as u32) >= 0xaa &&
567        super::bitset_search(
568            c as u32,
569            &BITSET_CHUNKS_MAP,
570            &BITSET_INDEX_CHUNKS,
571            &BITSET_CANONICAL,
572            &BITSET_MAPPING,
573        )
574    }
575}
576
577#[rustfmt::skip]
578pub mod n {
579    use super::ShortOffsetRunHeader;
580
581    static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 43] = [
582        ShortOffsetRunHeader::new(0, 1632), ShortOffsetRunHeader::new(7, 2406),
583        ShortOffsetRunHeader::new(13, 4160), ShortOffsetRunHeader::new(47, 4969),
584        ShortOffsetRunHeader::new(51, 5870), ShortOffsetRunHeader::new(53, 6470),
585        ShortOffsetRunHeader::new(61, 8304), ShortOffsetRunHeader::new(77, 9312),
586        ShortOffsetRunHeader::new(87, 10102), ShortOffsetRunHeader::new(91, 11517),
587        ShortOffsetRunHeader::new(93, 12295), ShortOffsetRunHeader::new(95, 12690),
588        ShortOffsetRunHeader::new(101, 42528), ShortOffsetRunHeader::new(113, 43056),
589        ShortOffsetRunHeader::new(117, 44016), ShortOffsetRunHeader::new(129, 65296),
590        ShortOffsetRunHeader::new(131, 65799), ShortOffsetRunHeader::new(133, 66273),
591        ShortOffsetRunHeader::new(139, 67672), ShortOffsetRunHeader::new(151, 68858),
592        ShortOffsetRunHeader::new(181, 69216), ShortOffsetRunHeader::new(187, 70736),
593        ShortOffsetRunHeader::new(207, 71248), ShortOffsetRunHeader::new(211, 71904),
594        ShortOffsetRunHeader::new(219, 72688), ShortOffsetRunHeader::new(223, 73552),
595        ShortOffsetRunHeader::new(233, 74752), ShortOffsetRunHeader::new(237, 90416),
596        ShortOffsetRunHeader::new(239, 92768), ShortOffsetRunHeader::new(241, 93552),
597        ShortOffsetRunHeader::new(249, 93824), ShortOffsetRunHeader::new(251, 94196),
598        ShortOffsetRunHeader::new(253, 118000), ShortOffsetRunHeader::new(255, 119488),
599        ShortOffsetRunHeader::new(257, 120782), ShortOffsetRunHeader::new(263, 123200),
600        ShortOffsetRunHeader::new(265, 123632), ShortOffsetRunHeader::new(267, 124144),
601        ShortOffsetRunHeader::new(269, 125127), ShortOffsetRunHeader::new(273, 126065),
602        ShortOffsetRunHeader::new(277, 127232), ShortOffsetRunHeader::new(287, 130032),
603        ShortOffsetRunHeader::new(289, 1244154),
604    ];
605    static OFFSETS: [u8; 291] = [
606        178, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118, 10, 118,
607        10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10, 70, 20,
608        0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10, 182, 10,
609        86, 10, 134, 10, 6, 10, 0, 1, 3, 6, 6, 10, 198, 51, 2, 5, 0, 60, 78, 22, 0, 30, 0, 1, 0, 1,
610        25, 9, 14, 3, 0, 4, 138, 10, 30, 8, 1, 15, 32, 10, 39, 15, 0, 10, 188, 10, 0, 6, 154, 10,
611        38, 10, 198, 10, 22, 10, 86, 10, 0, 10, 0, 10, 0, 45, 12, 57, 17, 2, 0, 27, 36, 4, 29, 1, 8,
612        1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9, 52, 2,
613        30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 6, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134,
614        30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 6, 20, 76, 12,
615        0, 19, 93, 10, 0, 10, 86, 29, 227, 10, 70, 10, 54, 10, 0, 10, 102, 21, 0, 111, 0, 10, 0, 10,
616        86, 10, 134, 10, 1, 7, 0, 10, 0, 23, 0, 3, 0, 10, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0,
617        10, 0, 10, 247, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0, 10, 0,
618    ];
619    #[inline]
620    pub fn lookup(c: char) -> bool {
621        debug_assert!(!c.is_ascii());
622        (c as u32) >= 0xb2 && lookup_slow(c)
623    }
624
625    #[inline(never)]
626    fn lookup_slow(c: char) -> bool {
627        const {
628            assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32);
629            let mut i = 0;
630            while i < SHORT_OFFSET_RUNS.len() {
631                assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len());
632                i += 1;
633            }
634        }
635        // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX`
636        // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`.
637        unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) }
638    }
639}
640
641#[rustfmt::skip]
642pub mod uppercase {
643    static BITSET_CHUNKS_MAP: [u8; 125] = [
644        3, 14, 6, 6, 0, 6, 6, 2, 5, 12, 6, 15, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
645        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
646        6, 6, 6, 7, 6, 13, 6, 11, 6, 6, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
647        6, 8, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 16, 6, 6,
648        6, 6, 10, 6, 4,
649    ];
650    static BITSET_INDEX_CHUNKS: [[u8; 16]; 17] = [
651        [44, 44, 5, 35, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 5, 0],
652        [44, 44, 5, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
653        [44, 44, 40, 44, 44, 44, 44, 44, 17, 17, 66, 17, 43, 29, 24, 23],
654        [44, 44, 44, 32, 36, 21, 22, 15, 13, 34, 44, 44, 44, 11, 30, 39],
655        [44, 44, 44, 44, 9, 8, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44],
656        [44, 44, 44, 44, 37, 28, 67, 44, 44, 44, 44, 44, 44, 44, 44, 44],
657        [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
658        [44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 57, 44, 44, 44],
659        [44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 63, 44, 44, 44, 44, 44],
660        [44, 44, 44, 44, 44, 44, 44, 44, 44, 65, 64, 44, 20, 14, 16, 4],
661        [44, 44, 44, 44, 50, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
662        [44, 44, 53, 44, 44, 31, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
663        [44, 44, 54, 46, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
664        [51, 44, 9, 47, 44, 42, 33, 44, 44, 44, 44, 44, 44, 44, 44, 44],
665        [52, 19, 3, 18, 10, 48, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
666        [52, 38, 17, 27, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44],
667        [58, 1, 26, 55, 12, 7, 25, 56, 41, 59, 6, 2, 62, 61, 60, 68],
668    ];
669    static BITSET_CANONICAL: [u64; 44] = [
670        0b0000000000111111111111111111111111111111111111111111111111111111,
671        0b1111111111111111111111110000000000000000000000000011111111111111,
672        0b0000011111111111111111111111110000000000000000000000000000000001,
673        0b0101010101010101010101010101010101010101010101010101010000000001,
674        0b0000000000100000000000000000000000010101010101010101101011110101,
675        0b1111111111111111111111111111111100000000000000000000000000000000,
676        0b1111111111111111111111110000000000000000000000000000001111111111,
677        0b1111111111111111111100000000000000000000000000011111110001011111,
678        0b1111111111111111000000111111111111111111111111110000001111111111,
679        0b1111111111111111000000000000000000000000000000000000000000000000,
680        0b1111111111111110010101010101010101010101010101010101010101010101,
681        0b1000000001000101000000000000000000000000000000000000000000000000,
682        0b0111101100000000000000000000000000011111110111111110011110110000,
683        0b0110110000000101010101010101010101010101010101010101010101010101,
684        0b0110101000000000010101010101010101010101010101010101010101010101,
685        0b0101010111010010010101010101010101001010101010101010010010010000,
686        0b0101010101011111011111010101010101010101010001010010100001010101,
687        0b0101010101010101010101010101010101010101010101010101010101010101,
688        0b0101010101010101010101010101010101010101010101010010101010101011,
689        0b0101010101010101010101010101010100000000000000000000000000000000,
690        0b0101010101010100010101010101010000000000000000000000000000000000,
691        0b0010101101010101010101010101010101010101010101010101010010101010,
692        0b0001000110101110110100101101010110110001110110111100111011010110,
693        0b0000111100000000000111110000000000001111000000000000111100000000,
694        0b0000111100000000000000000000000000000000000000000000000000000000,
695        0b0000001111111111111111111111111100000000000000000000000000111111,
696        0b0000000000111111110111100110010011010000000000000000000000000011,
697        0b0000000000000100001010000000010101010101010101010101010101010101,
698        0b0000000000000000111111111111111100000000000000000000000000100000,
699        0b0000000000000000111111110000000010101010000000000011111100000000,
700        0b0000000000000000000011111111101111111111111111101101011101000000,
701        0b0000000000000000000000000011111111111111111111110000000000000000,
702        0b0000000000000000000000000000000001111111011111111111111111111111,
703        0b0000000000000000000000000000000000000000001101111111011111111111,
704        0b0000000000000000000000000000000000000000000000000101010101111010,
705        0b0000000000000000000000000000000000000000000000000010000010111111,
706        0b1010101001010101010101010101010101010101010101010101010101010101,
707        0b1100000000001111001111010101000000111110001001110011100010000100,
708        0b1100000000100101111010101001110100000000000000000000000000000000,
709        0b1110011010010000010101010101010101010101000111001000000000000000,
710        0b1110011111111111111111111111111111111111111111110000001000000000,
711        0b1111000000000000000000000000001111111111111111111111111100000000,
712        0b1111011111111111000000000000000000000000000000000000000000000000,
713        0b1111111100000000111111110000000000111111000000001111111100000000,
714    ];
715    static BITSET_MAPPING: [(u8, u8); 25] = [
716        (0, 182), (0, 74), (0, 166), (0, 162), (0, 159), (0, 150), (0, 148), (0, 142), (0, 134),
717        (0, 131), (0, 64), (1, 66), (1, 70), (1, 83), (1, 12), (1, 8), (2, 146), (2, 140), (2, 134),
718        (2, 130), (3, 164), (3, 146), (3, 20), (4, 178), (4, 171),
719    ];
720
721    pub const fn lookup(c: char) -> bool {
722        debug_assert!(!c.is_ascii());
723        (c as u32) >= 0xc0 &&
724        super::bitset_search(
725            c as u32,
726            &BITSET_CHUNKS_MAP,
727            &BITSET_INDEX_CHUNKS,
728            &BITSET_CANONICAL,
729            &BITSET_MAPPING,
730        )
731    }
732}
733
734#[rustfmt::skip]
735pub mod white_space {
736    static WHITESPACE_MAP: [u8; 256] = [
737        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
738        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
739        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
740        0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
741        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
742        0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
743        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
744        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
745        0, 0, 0, 0, 0, 0, 0, 0, 0,
746    ];
747    #[inline]
748    pub const fn lookup(c: char) -> bool {
749        debug_assert!(!c.is_ascii());
750        match c as u32 >> 8 {
751            0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0,
752            22 => c as u32 == 0x1680,
753            32 => WHITESPACE_MAP[c as usize & 0xff] & 2 != 0,
754            48 => c as u32 == 0x3000,
755            _ => false,
756        }
757    }
758}
759
760#[rustfmt::skip]
761pub mod conversions {
762
763
764    use crate::ops::RangeInclusive;
765
766    struct L1Lut {
767        l2_luts: [L2Lut; 2],
768    }
769
770    struct L2Lut {
771        singles: &'static [(Range, i16)],
772        multis: &'static [(u16, [u16; 3])],
773    }
774
775    #[derive(Copy, Clone)]
776    struct Range {
777        start: u16,
778        len: u8,
779        parity: bool,
780    }
781
782    impl Range {
783        const fn new(range: RangeInclusive<u16>, parity: bool) -> Self {
784            let start = *range.start();
785            let end = *range.end();
786            assert!(start <= end);
787
788            let len = end - start;
789            assert!(len <= 255);
790
791            Self { start, len: len as u8, parity }
792        }
793
794        const fn singleton(start: u16) -> Self {
795            Self::new(start..=start, false)
796        }
797
798        const fn step_by_1(range: RangeInclusive<u16>) -> Self {
799            Self::new(range, false)
800        }
801
802        const fn step_by_2(range: RangeInclusive<u16>) -> Self {
803            Self::new(range, true)
804        }
805
806        const fn start(&self) -> u16 {
807            self.start
808        }
809
810        const fn end(&self) -> u16 {
811            self.start + self.len as u16
812        }
813    }
814
815    fn deconstruct(c: char) -> (u16, u16) {
816        let c = c as u32;
817        let plane = (c >> 16) as u16;
818        let low = c as u16;
819        (plane, low)
820    }
821
822    unsafe fn reconstruct(plane: u16, low: u16) -> char {
823        // SAFETY: The caller must ensure that the result is a valid `char`.
824        unsafe { char::from_u32_unchecked(((plane as u32) << 16) | (low as u32)) }
825    }
826
827    fn lookup(input: char, l1_lut: &L1Lut) -> Option<[char; 3]> {
828        let (input_high, input_low) = deconstruct(input);
829        let Some(l2_lut) = l1_lut.l2_luts.get(input_high as usize) else {
830            return None;
831        };
832
833        let idx = l2_lut.singles.binary_search_by(|(range, _)| {
834            use crate::cmp::Ordering;
835
836            if input_low < range.start() {
837                Ordering::Greater
838            } else if input_low > range.end() {
839                Ordering::Less
840            } else {
841                Ordering::Equal
842            }
843        });
844
845        if let Ok(idx) = idx {
846            // SAFETY: binary search guarantees that the index is in bounds.
847            let &(range, output_delta) = unsafe { l2_lut.singles.get_unchecked(idx) };
848            let mask = range.parity as u16;
849            if input_low & mask == range.start() & mask {
850                let output_low = input_low.wrapping_add_signed(output_delta);
851                // SAFETY: Table data are guaranteed to be valid Unicode.
852                let output = unsafe { reconstruct(input_high, output_low) };
853                return Some([output, '\0', '\0']);
854            }
855        };
856
857        if let Ok(idx) = l2_lut.multis.binary_search_by_key(&input_low, |&(p, _)| p) {
858            // SAFETY: binary search guarantees that the index is in bounds.
859            let &(_, output_lows) = unsafe { l2_lut.multis.get_unchecked(idx) };
860            // SAFETY: Table data are guaranteed to be valid Unicode.
861            let output = output_lows.map(|output_low| unsafe { reconstruct(input_high, output_low) });
862            return Some(output);
863        };
864
865        None
866    }
867
868    pub fn to_lower(c: char) -> [char; 3] {
869        // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Lowercased%253A%5D-%5B%253AASCII%253A%5D&abb=on
870        if c < '\u{C0}' {
871            return [c.to_ascii_lowercase(), '\0', '\0'];
872        }
873
874        lookup(c, &LOWERCASE_LUT).unwrap_or([c, '\0', '\0'])
875    }
876
877    pub fn to_upper(c: char) -> [char; 3] {
878        // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Uppercased%253A%5D-%5B%253AASCII%253A%5D&abb=on
879        if c < '\u{B5}' {
880            return [c.to_ascii_uppercase(), '\0', '\0'];
881        }
882
883        lookup(c, &UPPERCASE_LUT).unwrap_or([c, '\0', '\0'])
884    }
885
886    pub fn to_title(c: char) -> [char; 3] {
887        // https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5B%253AChanges_When_Titlecased%253A%5D-%5B%253AASCII%253A%5D&abb=on
888        if c < '\u{B5}' {
889            return [c.to_ascii_uppercase(), '\0', '\0'];
890        }
891
892        lookup(c, &TITLECASE_LUT).or_else(|| lookup(c, &UPPERCASE_LUT)).unwrap_or([c, '\0', '\0'])
893    }
894
895    static LOWERCASE_LUT: L1Lut = L1Lut {
896        l2_luts: [
897            L2Lut {
898                singles: &[ // 172 entries, 1032 bytes
899                    (Range::step_by_1(0x00c0..=0x00d6), 32), (Range::step_by_1(0x00d8..=0x00de), 32),
900                    (Range::step_by_2(0x0100..=0x012e), 1), (Range::step_by_2(0x0132..=0x0136), 1),
901                    (Range::step_by_2(0x0139..=0x0147), 1), (Range::step_by_2(0x014a..=0x0176), 1),
902                    (Range::singleton(0x0178), -121), (Range::step_by_2(0x0179..=0x017d), 1),
903                    (Range::singleton(0x0181), 210), (Range::step_by_2(0x0182..=0x0184), 1),
904                    (Range::singleton(0x0186), 206), (Range::singleton(0x0187), 1),
905                    (Range::step_by_1(0x0189..=0x018a), 205), (Range::singleton(0x018b), 1),
906                    (Range::singleton(0x018e), 79), (Range::singleton(0x018f), 202),
907                    (Range::singleton(0x0190), 203), (Range::singleton(0x0191), 1),
908                    (Range::singleton(0x0193), 205), (Range::singleton(0x0194), 207),
909                    (Range::singleton(0x0196), 211), (Range::singleton(0x0197), 209),
910                    (Range::singleton(0x0198), 1), (Range::singleton(0x019c), 211),
911                    (Range::singleton(0x019d), 213), (Range::singleton(0x019f), 214),
912                    (Range::step_by_2(0x01a0..=0x01a4), 1), (Range::singleton(0x01a6), 218),
913                    (Range::singleton(0x01a7), 1), (Range::singleton(0x01a9), 218),
914                    (Range::singleton(0x01ac), 1), (Range::singleton(0x01ae), 218),
915                    (Range::singleton(0x01af), 1), (Range::step_by_1(0x01b1..=0x01b2), 217),
916                    (Range::step_by_2(0x01b3..=0x01b5), 1), (Range::singleton(0x01b7), 219),
917                    (Range::singleton(0x01b8), 1), (Range::singleton(0x01bc), 1), (Range::singleton(0x01c4), 2),
918                    (Range::singleton(0x01c5), 1), (Range::singleton(0x01c7), 2), (Range::singleton(0x01c8), 1),
919                    (Range::singleton(0x01ca), 2), (Range::step_by_2(0x01cb..=0x01db), 1),
920                    (Range::step_by_2(0x01de..=0x01ee), 1), (Range::singleton(0x01f1), 2),
921                    (Range::step_by_2(0x01f2..=0x01f4), 1), (Range::singleton(0x01f6), -97),
922                    (Range::singleton(0x01f7), -56), (Range::step_by_2(0x01f8..=0x021e), 1),
923                    (Range::singleton(0x0220), -130), (Range::step_by_2(0x0222..=0x0232), 1),
924                    (Range::singleton(0x023a), 10795), (Range::singleton(0x023b), 1),
925                    (Range::singleton(0x023d), -163), (Range::singleton(0x023e), 10792),
926                    (Range::singleton(0x0241), 1), (Range::singleton(0x0243), -195),
927                    (Range::singleton(0x0244), 69), (Range::singleton(0x0245), 71),
928                    (Range::step_by_2(0x0246..=0x024e), 1), (Range::step_by_2(0x0370..=0x0372), 1),
929                    (Range::singleton(0x0376), 1), (Range::singleton(0x037f), 116),
930                    (Range::singleton(0x0386), 38), (Range::step_by_1(0x0388..=0x038a), 37),
931                    (Range::singleton(0x038c), 64), (Range::step_by_1(0x038e..=0x038f), 63),
932                    (Range::step_by_1(0x0391..=0x03a1), 32), (Range::step_by_1(0x03a3..=0x03ab), 32),
933                    (Range::singleton(0x03cf), 8), (Range::step_by_2(0x03d8..=0x03ee), 1),
934                    (Range::singleton(0x03f4), -60), (Range::singleton(0x03f7), 1),
935                    (Range::singleton(0x03f9), -7), (Range::singleton(0x03fa), 1),
936                    (Range::step_by_1(0x03fd..=0x03ff), -130), (Range::step_by_1(0x0400..=0x040f), 80),
937                    (Range::step_by_1(0x0410..=0x042f), 32), (Range::step_by_2(0x0460..=0x0480), 1),
938                    (Range::step_by_2(0x048a..=0x04be), 1), (Range::singleton(0x04c0), 15),
939                    (Range::step_by_2(0x04c1..=0x04cd), 1), (Range::step_by_2(0x04d0..=0x052e), 1),
940                    (Range::step_by_1(0x0531..=0x0556), 48), (Range::step_by_1(0x10a0..=0x10c5), 7264),
941                    (Range::singleton(0x10c7), 7264), (Range::singleton(0x10cd), 7264),
942                    (Range::step_by_1(0x13a0..=0x13ef), -26672), (Range::step_by_1(0x13f0..=0x13f5), 8),
943                    (Range::singleton(0x1c89), 1), (Range::step_by_1(0x1c90..=0x1cba), -3008),
944                    (Range::step_by_1(0x1cbd..=0x1cbf), -3008), (Range::step_by_2(0x1e00..=0x1e94), 1),
945                    (Range::singleton(0x1e9e), -7615), (Range::step_by_2(0x1ea0..=0x1efe), 1),
946                    (Range::step_by_1(0x1f08..=0x1f0f), -8), (Range::step_by_1(0x1f18..=0x1f1d), -8),
947                    (Range::step_by_1(0x1f28..=0x1f2f), -8), (Range::step_by_1(0x1f38..=0x1f3f), -8),
948                    (Range::step_by_1(0x1f48..=0x1f4d), -8), (Range::step_by_2(0x1f59..=0x1f5f), -8),
949                    (Range::step_by_1(0x1f68..=0x1f6f), -8), (Range::step_by_1(0x1f88..=0x1f8f), -8),
950                    (Range::step_by_1(0x1f98..=0x1f9f), -8), (Range::step_by_1(0x1fa8..=0x1faf), -8),
951                    (Range::step_by_1(0x1fb8..=0x1fb9), -8), (Range::step_by_1(0x1fba..=0x1fbb), -74),
952                    (Range::singleton(0x1fbc), -9), (Range::step_by_1(0x1fc8..=0x1fcb), -86),
953                    (Range::singleton(0x1fcc), -9), (Range::step_by_1(0x1fd8..=0x1fd9), -8),
954                    (Range::step_by_1(0x1fda..=0x1fdb), -100), (Range::step_by_1(0x1fe8..=0x1fe9), -8),
955                    (Range::step_by_1(0x1fea..=0x1feb), -112), (Range::singleton(0x1fec), -7),
956                    (Range::step_by_1(0x1ff8..=0x1ff9), -128), (Range::step_by_1(0x1ffa..=0x1ffb), -126),
957                    (Range::singleton(0x1ffc), -9), (Range::singleton(0x2126), -7517),
958                    (Range::singleton(0x212a), -8383), (Range::singleton(0x212b), -8262),
959                    (Range::singleton(0x2132), 28), (Range::step_by_1(0x2160..=0x216f), 16),
960                    (Range::singleton(0x2183), 1), (Range::step_by_1(0x24b6..=0x24cf), 26),
961                    (Range::step_by_1(0x2c00..=0x2c2f), 48), (Range::singleton(0x2c60), 1),
962                    (Range::singleton(0x2c62), -10743), (Range::singleton(0x2c63), -3814),
963                    (Range::singleton(0x2c64), -10727), (Range::step_by_2(0x2c67..=0x2c6b), 1),
964                    (Range::singleton(0x2c6d), -10780), (Range::singleton(0x2c6e), -10749),
965                    (Range::singleton(0x2c6f), -10783), (Range::singleton(0x2c70), -10782),
966                    (Range::singleton(0x2c72), 1), (Range::singleton(0x2c75), 1),
967                    (Range::step_by_1(0x2c7e..=0x2c7f), -10815), (Range::step_by_2(0x2c80..=0x2ce2), 1),
968                    (Range::step_by_2(0x2ceb..=0x2ced), 1), (Range::singleton(0x2cf2), 1),
969                    (Range::step_by_2(0xa640..=0xa66c), 1), (Range::step_by_2(0xa680..=0xa69a), 1),
970                    (Range::step_by_2(0xa722..=0xa72e), 1), (Range::step_by_2(0xa732..=0xa76e), 1),
971                    (Range::step_by_2(0xa779..=0xa77b), 1), (Range::singleton(0xa77d), 30204),
972                    (Range::step_by_2(0xa77e..=0xa786), 1), (Range::singleton(0xa78b), 1),
973                    (Range::singleton(0xa78d), 23256), (Range::step_by_2(0xa790..=0xa792), 1),
974                    (Range::step_by_2(0xa796..=0xa7a8), 1), (Range::singleton(0xa7aa), 23228),
975                    (Range::singleton(0xa7ab), 23217), (Range::singleton(0xa7ac), 23221),
976                    (Range::singleton(0xa7ad), 23231), (Range::singleton(0xa7ae), 23228),
977                    (Range::singleton(0xa7b0), 23278), (Range::singleton(0xa7b1), 23254),
978                    (Range::singleton(0xa7b2), 23275), (Range::singleton(0xa7b3), 928),
979                    (Range::step_by_2(0xa7b4..=0xa7c2), 1), (Range::singleton(0xa7c4), -48),
980                    (Range::singleton(0xa7c5), 23229), (Range::singleton(0xa7c6), 30152),
981                    (Range::step_by_2(0xa7c7..=0xa7c9), 1), (Range::singleton(0xa7cb), 23193),
982                    (Range::step_by_2(0xa7cc..=0xa7da), 1), (Range::singleton(0xa7dc), 22975),
983                    (Range::singleton(0xa7f5), 1), (Range::step_by_1(0xff21..=0xff3a), 32),
984                ],
985                multis: &[ // 1 entries, 8 bytes
986                    (0x0130, [0x0069, 0x0307, 0x0000]),
987                ],
988            },
989            L2Lut {
990                singles: &[ // 12 entries, 72 bytes
991                    (Range::step_by_1(0x0400..=0x0427), 40), (Range::step_by_1(0x04b0..=0x04d3), 40),
992                    (Range::step_by_1(0x0570..=0x057a), 39), (Range::step_by_1(0x057c..=0x058a), 39),
993                    (Range::step_by_1(0x058c..=0x0592), 39), (Range::step_by_1(0x0594..=0x0595), 39),
994                    (Range::step_by_1(0x0c80..=0x0cb2), 64), (Range::step_by_1(0x0d50..=0x0d65), 32),
995                    (Range::step_by_1(0x18a0..=0x18bf), 32), (Range::step_by_1(0x6e40..=0x6e5f), 32),
996                    (Range::step_by_1(0x6ea0..=0x6eb8), 27), (Range::step_by_1(0xe900..=0xe921), 34),
997                ],
998                multis: &[ // 0 entries, 0 bytes
999                ],
1000            },
1001        ],
1002    };
1003
1004    static UPPERCASE_LUT: L1Lut = L1Lut {
1005        l2_luts: [
1006            L2Lut {
1007                singles: &[ // 185 entries, 1110 bytes
1008                    (Range::singleton(0x00b5), 743), (Range::step_by_1(0x00e0..=0x00f6), -32),
1009                    (Range::step_by_1(0x00f8..=0x00fe), -32), (Range::singleton(0x00ff), 121),
1010                    (Range::step_by_2(0x0101..=0x012f), -1), (Range::singleton(0x0131), -232),
1011                    (Range::step_by_2(0x0133..=0x0137), -1), (Range::step_by_2(0x013a..=0x0148), -1),
1012                    (Range::step_by_2(0x014b..=0x0177), -1), (Range::step_by_2(0x017a..=0x017e), -1),
1013                    (Range::singleton(0x017f), -300), (Range::singleton(0x0180), 195),
1014                    (Range::step_by_2(0x0183..=0x0185), -1), (Range::singleton(0x0188), -1),
1015                    (Range::singleton(0x018c), -1), (Range::singleton(0x0192), -1),
1016                    (Range::singleton(0x0195), 97), (Range::singleton(0x0199), -1),
1017                    (Range::singleton(0x019a), 163), (Range::singleton(0x019b), -22975),
1018                    (Range::singleton(0x019e), 130), (Range::step_by_2(0x01a1..=0x01a5), -1),
1019                    (Range::singleton(0x01a8), -1), (Range::singleton(0x01ad), -1),
1020                    (Range::singleton(0x01b0), -1), (Range::step_by_2(0x01b4..=0x01b6), -1),
1021                    (Range::singleton(0x01b9), -1), (Range::singleton(0x01bd), -1),
1022                    (Range::singleton(0x01bf), 56), (Range::singleton(0x01c5), -1),
1023                    (Range::singleton(0x01c6), -2), (Range::singleton(0x01c8), -1),
1024                    (Range::singleton(0x01c9), -2), (Range::singleton(0x01cb), -1),
1025                    (Range::singleton(0x01cc), -2), (Range::step_by_2(0x01ce..=0x01dc), -1),
1026                    (Range::singleton(0x01dd), -79), (Range::step_by_2(0x01df..=0x01ef), -1),
1027                    (Range::singleton(0x01f2), -1), (Range::singleton(0x01f3), -2),
1028                    (Range::singleton(0x01f5), -1), (Range::step_by_2(0x01f9..=0x021f), -1),
1029                    (Range::step_by_2(0x0223..=0x0233), -1), (Range::singleton(0x023c), -1),
1030                    (Range::step_by_1(0x023f..=0x0240), 10815), (Range::singleton(0x0242), -1),
1031                    (Range::step_by_2(0x0247..=0x024f), -1), (Range::singleton(0x0250), 10783),
1032                    (Range::singleton(0x0251), 10780), (Range::singleton(0x0252), 10782),
1033                    (Range::singleton(0x0253), -210), (Range::singleton(0x0254), -206),
1034                    (Range::step_by_1(0x0256..=0x0257), -205), (Range::singleton(0x0259), -202),
1035                    (Range::singleton(0x025b), -203), (Range::singleton(0x025c), -23217),
1036                    (Range::singleton(0x0260), -205), (Range::singleton(0x0261), -23221),
1037                    (Range::singleton(0x0263), -207), (Range::singleton(0x0264), -23193),
1038                    (Range::singleton(0x0265), -23256), (Range::singleton(0x0266), -23228),
1039                    (Range::singleton(0x0268), -209), (Range::singleton(0x0269), -211),
1040                    (Range::singleton(0x026a), -23228), (Range::singleton(0x026b), 10743),
1041                    (Range::singleton(0x026c), -23231), (Range::singleton(0x026f), -211),
1042                    (Range::singleton(0x0271), 10749), (Range::singleton(0x0272), -213),
1043                    (Range::singleton(0x0275), -214), (Range::singleton(0x027d), 10727),
1044                    (Range::singleton(0x0280), -218), (Range::singleton(0x0282), -23229),
1045                    (Range::singleton(0x0283), -218), (Range::singleton(0x0287), -23254),
1046                    (Range::singleton(0x0288), -218), (Range::singleton(0x0289), -69),
1047                    (Range::step_by_1(0x028a..=0x028b), -217), (Range::singleton(0x028c), -71),
1048                    (Range::singleton(0x0292), -219), (Range::singleton(0x029d), -23275),
1049                    (Range::singleton(0x029e), -23278), (Range::singleton(0x0345), 84),
1050                    (Range::step_by_2(0x0371..=0x0373), -1), (Range::singleton(0x0377), -1),
1051                    (Range::step_by_1(0x037b..=0x037d), 130), (Range::singleton(0x03ac), -38),
1052                    (Range::step_by_1(0x03ad..=0x03af), -37), (Range::step_by_1(0x03b1..=0x03c1), -32),
1053                    (Range::singleton(0x03c2), -31), (Range::step_by_1(0x03c3..=0x03cb), -32),
1054                    (Range::singleton(0x03cc), -64), (Range::step_by_1(0x03cd..=0x03ce), -63),
1055                    (Range::singleton(0x03d0), -62), (Range::singleton(0x03d1), -57),
1056                    (Range::singleton(0x03d5), -47), (Range::singleton(0x03d6), -54),
1057                    (Range::singleton(0x03d7), -8), (Range::step_by_2(0x03d9..=0x03ef), -1),
1058                    (Range::singleton(0x03f0), -86), (Range::singleton(0x03f1), -80),
1059                    (Range::singleton(0x03f2), 7), (Range::singleton(0x03f3), -116),
1060                    (Range::singleton(0x03f5), -96), (Range::singleton(0x03f8), -1),
1061                    (Range::singleton(0x03fb), -1), (Range::step_by_1(0x0430..=0x044f), -32),
1062                    (Range::step_by_1(0x0450..=0x045f), -80), (Range::step_by_2(0x0461..=0x0481), -1),
1063                    (Range::step_by_2(0x048b..=0x04bf), -1), (Range::step_by_2(0x04c2..=0x04ce), -1),
1064                    (Range::singleton(0x04cf), -15), (Range::step_by_2(0x04d1..=0x052f), -1),
1065                    (Range::step_by_1(0x0561..=0x0586), -48), (Range::step_by_1(0x10d0..=0x10fa), 3008),
1066                    (Range::step_by_1(0x10fd..=0x10ff), 3008), (Range::step_by_1(0x13f8..=0x13fd), -8),
1067                    (Range::singleton(0x1c80), -6254), (Range::singleton(0x1c81), -6253),
1068                    (Range::singleton(0x1c82), -6244), (Range::step_by_1(0x1c83..=0x1c84), -6242),
1069                    (Range::singleton(0x1c85), -6243), (Range::singleton(0x1c86), -6236),
1070                    (Range::singleton(0x1c87), -6181), (Range::singleton(0x1c88), -30270),
1071                    (Range::singleton(0x1c8a), -1), (Range::singleton(0x1d79), -30204),
1072                    (Range::singleton(0x1d7d), 3814), (Range::singleton(0x1d8e), -30152),
1073                    (Range::step_by_2(0x1e01..=0x1e95), -1), (Range::singleton(0x1e9b), -59),
1074                    (Range::step_by_2(0x1ea1..=0x1eff), -1), (Range::step_by_1(0x1f00..=0x1f07), 8),
1075                    (Range::step_by_1(0x1f10..=0x1f15), 8), (Range::step_by_1(0x1f20..=0x1f27), 8),
1076                    (Range::step_by_1(0x1f30..=0x1f37), 8), (Range::step_by_1(0x1f40..=0x1f45), 8),
1077                    (Range::step_by_2(0x1f51..=0x1f57), 8), (Range::step_by_1(0x1f60..=0x1f67), 8),
1078                    (Range::step_by_1(0x1f70..=0x1f71), 74), (Range::step_by_1(0x1f72..=0x1f75), 86),
1079                    (Range::step_by_1(0x1f76..=0x1f77), 100), (Range::step_by_1(0x1f78..=0x1f79), 128),
1080                    (Range::step_by_1(0x1f7a..=0x1f7b), 112), (Range::step_by_1(0x1f7c..=0x1f7d), 126),
1081                    (Range::step_by_1(0x1fb0..=0x1fb1), 8), (Range::singleton(0x1fbe), -7205),
1082                    (Range::step_by_1(0x1fd0..=0x1fd1), 8), (Range::step_by_1(0x1fe0..=0x1fe1), 8),
1083                    (Range::singleton(0x1fe5), 7), (Range::singleton(0x214e), -28),
1084                    (Range::step_by_1(0x2170..=0x217f), -16), (Range::singleton(0x2184), -1),
1085                    (Range::step_by_1(0x24d0..=0x24e9), -26), (Range::step_by_1(0x2c30..=0x2c5f), -48),
1086                    (Range::singleton(0x2c61), -1), (Range::singleton(0x2c65), -10795),
1087                    (Range::singleton(0x2c66), -10792), (Range::step_by_2(0x2c68..=0x2c6c), -1),
1088                    (Range::singleton(0x2c73), -1), (Range::singleton(0x2c76), -1),
1089                    (Range::step_by_2(0x2c81..=0x2ce3), -1), (Range::step_by_2(0x2cec..=0x2cee), -1),
1090                    (Range::singleton(0x2cf3), -1), (Range::step_by_1(0x2d00..=0x2d25), -7264),
1091                    (Range::singleton(0x2d27), -7264), (Range::singleton(0x2d2d), -7264),
1092                    (Range::step_by_2(0xa641..=0xa66d), -1), (Range::step_by_2(0xa681..=0xa69b), -1),
1093                    (Range::step_by_2(0xa723..=0xa72f), -1), (Range::step_by_2(0xa733..=0xa76f), -1),
1094                    (Range::step_by_2(0xa77a..=0xa77c), -1), (Range::step_by_2(0xa77f..=0xa787), -1),
1095                    (Range::singleton(0xa78c), -1), (Range::step_by_2(0xa791..=0xa793), -1),
1096                    (Range::singleton(0xa794), 48), (Range::step_by_2(0xa797..=0xa7a9), -1),
1097                    (Range::step_by_2(0xa7b5..=0xa7c3), -1), (Range::step_by_2(0xa7c8..=0xa7ca), -1),
1098                    (Range::step_by_2(0xa7cd..=0xa7db), -1), (Range::singleton(0xa7f6), -1),
1099                    (Range::singleton(0xab53), -928), (Range::step_by_1(0xab70..=0xabbf), 26672),
1100                    (Range::step_by_1(0xff41..=0xff5a), -32),
1101                ],
1102                multis: &[ // 102 entries, 816 bytes
1103                    (0x00df, [0x0053, 0x0053, 0x0000]), (0x0149, [0x02bc, 0x004e, 0x0000]),
1104                    (0x01f0, [0x004a, 0x030c, 0x0000]), (0x0390, [0x0399, 0x0308, 0x0301]),
1105                    (0x03b0, [0x03a5, 0x0308, 0x0301]), (0x0587, [0x0535, 0x0552, 0x0000]),
1106                    (0x1e96, [0x0048, 0x0331, 0x0000]), (0x1e97, [0x0054, 0x0308, 0x0000]),
1107                    (0x1e98, [0x0057, 0x030a, 0x0000]), (0x1e99, [0x0059, 0x030a, 0x0000]),
1108                    (0x1e9a, [0x0041, 0x02be, 0x0000]), (0x1f50, [0x03a5, 0x0313, 0x0000]),
1109                    (0x1f52, [0x03a5, 0x0313, 0x0300]), (0x1f54, [0x03a5, 0x0313, 0x0301]),
1110                    (0x1f56, [0x03a5, 0x0313, 0x0342]), (0x1f80, [0x1f08, 0x0399, 0x0000]),
1111                    (0x1f81, [0x1f09, 0x0399, 0x0000]), (0x1f82, [0x1f0a, 0x0399, 0x0000]),
1112                    (0x1f83, [0x1f0b, 0x0399, 0x0000]), (0x1f84, [0x1f0c, 0x0399, 0x0000]),
1113                    (0x1f85, [0x1f0d, 0x0399, 0x0000]), (0x1f86, [0x1f0e, 0x0399, 0x0000]),
1114                    (0x1f87, [0x1f0f, 0x0399, 0x0000]), (0x1f88, [0x1f08, 0x0399, 0x0000]),
1115                    (0x1f89, [0x1f09, 0x0399, 0x0000]), (0x1f8a, [0x1f0a, 0x0399, 0x0000]),
1116                    (0x1f8b, [0x1f0b, 0x0399, 0x0000]), (0x1f8c, [0x1f0c, 0x0399, 0x0000]),
1117                    (0x1f8d, [0x1f0d, 0x0399, 0x0000]), (0x1f8e, [0x1f0e, 0x0399, 0x0000]),
1118                    (0x1f8f, [0x1f0f, 0x0399, 0x0000]), (0x1f90, [0x1f28, 0x0399, 0x0000]),
1119                    (0x1f91, [0x1f29, 0x0399, 0x0000]), (0x1f92, [0x1f2a, 0x0399, 0x0000]),
1120                    (0x1f93, [0x1f2b, 0x0399, 0x0000]), (0x1f94, [0x1f2c, 0x0399, 0x0000]),
1121                    (0x1f95, [0x1f2d, 0x0399, 0x0000]), (0x1f96, [0x1f2e, 0x0399, 0x0000]),
1122                    (0x1f97, [0x1f2f, 0x0399, 0x0000]), (0x1f98, [0x1f28, 0x0399, 0x0000]),
1123                    (0x1f99, [0x1f29, 0x0399, 0x0000]), (0x1f9a, [0x1f2a, 0x0399, 0x0000]),
1124                    (0x1f9b, [0x1f2b, 0x0399, 0x0000]), (0x1f9c, [0x1f2c, 0x0399, 0x0000]),
1125                    (0x1f9d, [0x1f2d, 0x0399, 0x0000]), (0x1f9e, [0x1f2e, 0x0399, 0x0000]),
1126                    (0x1f9f, [0x1f2f, 0x0399, 0x0000]), (0x1fa0, [0x1f68, 0x0399, 0x0000]),
1127                    (0x1fa1, [0x1f69, 0x0399, 0x0000]), (0x1fa2, [0x1f6a, 0x0399, 0x0000]),
1128                    (0x1fa3, [0x1f6b, 0x0399, 0x0000]), (0x1fa4, [0x1f6c, 0x0399, 0x0000]),
1129                    (0x1fa5, [0x1f6d, 0x0399, 0x0000]), (0x1fa6, [0x1f6e, 0x0399, 0x0000]),
1130                    (0x1fa7, [0x1f6f, 0x0399, 0x0000]), (0x1fa8, [0x1f68, 0x0399, 0x0000]),
1131                    (0x1fa9, [0x1f69, 0x0399, 0x0000]), (0x1faa, [0x1f6a, 0x0399, 0x0000]),
1132                    (0x1fab, [0x1f6b, 0x0399, 0x0000]), (0x1fac, [0x1f6c, 0x0399, 0x0000]),
1133                    (0x1fad, [0x1f6d, 0x0399, 0x0000]), (0x1fae, [0x1f6e, 0x0399, 0x0000]),
1134                    (0x1faf, [0x1f6f, 0x0399, 0x0000]), (0x1fb2, [0x1fba, 0x0399, 0x0000]),
1135                    (0x1fb3, [0x0391, 0x0399, 0x0000]), (0x1fb4, [0x0386, 0x0399, 0x0000]),
1136                    (0x1fb6, [0x0391, 0x0342, 0x0000]), (0x1fb7, [0x0391, 0x0342, 0x0399]),
1137                    (0x1fbc, [0x0391, 0x0399, 0x0000]), (0x1fc2, [0x1fca, 0x0399, 0x0000]),
1138                    (0x1fc3, [0x0397, 0x0399, 0x0000]), (0x1fc4, [0x0389, 0x0399, 0x0000]),
1139                    (0x1fc6, [0x0397, 0x0342, 0x0000]), (0x1fc7, [0x0397, 0x0342, 0x0399]),
1140                    (0x1fcc, [0x0397, 0x0399, 0x0000]), (0x1fd2, [0x0399, 0x0308, 0x0300]),
1141                    (0x1fd3, [0x0399, 0x0308, 0x0301]), (0x1fd6, [0x0399, 0x0342, 0x0000]),
1142                    (0x1fd7, [0x0399, 0x0308, 0x0342]), (0x1fe2, [0x03a5, 0x0308, 0x0300]),
1143                    (0x1fe3, [0x03a5, 0x0308, 0x0301]), (0x1fe4, [0x03a1, 0x0313, 0x0000]),
1144                    (0x1fe6, [0x03a5, 0x0342, 0x0000]), (0x1fe7, [0x03a5, 0x0308, 0x0342]),
1145                    (0x1ff2, [0x1ffa, 0x0399, 0x0000]), (0x1ff3, [0x03a9, 0x0399, 0x0000]),
1146                    (0x1ff4, [0x038f, 0x0399, 0x0000]), (0x1ff6, [0x03a9, 0x0342, 0x0000]),
1147                    (0x1ff7, [0x03a9, 0x0342, 0x0399]), (0x1ffc, [0x03a9, 0x0399, 0x0000]),
1148                    (0xfb00, [0x0046, 0x0046, 0x0000]), (0xfb01, [0x0046, 0x0049, 0x0000]),
1149                    (0xfb02, [0x0046, 0x004c, 0x0000]), (0xfb03, [0x0046, 0x0046, 0x0049]),
1150                    (0xfb04, [0x0046, 0x0046, 0x004c]), (0xfb05, [0x0053, 0x0054, 0x0000]),
1151                    (0xfb06, [0x0053, 0x0054, 0x0000]), (0xfb13, [0x0544, 0x0546, 0x0000]),
1152                    (0xfb14, [0x0544, 0x0535, 0x0000]), (0xfb15, [0x0544, 0x053b, 0x0000]),
1153                    (0xfb16, [0x054e, 0x0546, 0x0000]), (0xfb17, [0x0544, 0x053d, 0x0000]),
1154                ],
1155            },
1156            L2Lut {
1157                singles: &[ // 12 entries, 72 bytes
1158                    (Range::step_by_1(0x0428..=0x044f), -40), (Range::step_by_1(0x04d8..=0x04fb), -40),
1159                    (Range::step_by_1(0x0597..=0x05a1), -39), (Range::step_by_1(0x05a3..=0x05b1), -39),
1160                    (Range::step_by_1(0x05b3..=0x05b9), -39), (Range::step_by_1(0x05bb..=0x05bc), -39),
1161                    (Range::step_by_1(0x0cc0..=0x0cf2), -64), (Range::step_by_1(0x0d70..=0x0d85), -32),
1162                    (Range::step_by_1(0x18c0..=0x18df), -32), (Range::step_by_1(0x6e60..=0x6e7f), -32),
1163                    (Range::step_by_1(0x6ebb..=0x6ed3), -27), (Range::step_by_1(0xe922..=0xe943), -34),
1164                ],
1165                multis: &[ // 0 entries, 0 bytes
1166                ],
1167            },
1168        ],
1169    };
1170
1171    static TITLECASE_LUT: L1Lut = L1Lut {
1172        l2_luts: [
1173            L2Lut {
1174                singles: &[ // 26 entries, 156 bytes
1175                    (Range::singleton(0x01c4), 1), (Range::singleton(0x01c5), 0),
1176                    (Range::singleton(0x01c6), -1), (Range::singleton(0x01c7), 1),
1177                    (Range::singleton(0x01c8), 0), (Range::singleton(0x01c9), -1),
1178                    (Range::singleton(0x01ca), 1), (Range::singleton(0x01cb), 0),
1179                    (Range::singleton(0x01cc), -1), (Range::singleton(0x01f1), 1),
1180                    (Range::singleton(0x01f2), 0), (Range::singleton(0x01f3), -1),
1181                    (Range::step_by_1(0x10d0..=0x10fa), 0), (Range::step_by_1(0x10fd..=0x10ff), 0),
1182                    (Range::step_by_1(0x1f80..=0x1f87), 8), (Range::step_by_1(0x1f88..=0x1f8f), 0),
1183                    (Range::step_by_1(0x1f90..=0x1f97), 8), (Range::step_by_1(0x1f98..=0x1f9f), 0),
1184                    (Range::step_by_1(0x1fa0..=0x1fa7), 8), (Range::step_by_1(0x1fa8..=0x1faf), 0),
1185                    (Range::singleton(0x1fb3), 9), (Range::singleton(0x1fbc), 0), (Range::singleton(0x1fc3), 9),
1186                    (Range::singleton(0x1fcc), 0), (Range::singleton(0x1ff3), 9), (Range::singleton(0x1ffc), 0),
1187                ],
1188                multis: &[ // 23 entries, 184 bytes
1189                    (0x00df, [0x0053, 0x0073, 0x0000]), (0x0587, [0x0535, 0x0582, 0x0000]),
1190                    (0x1fb2, [0x1fba, 0x0345, 0x0000]), (0x1fb4, [0x0386, 0x0345, 0x0000]),
1191                    (0x1fb7, [0x0391, 0x0342, 0x0345]), (0x1fc2, [0x1fca, 0x0345, 0x0000]),
1192                    (0x1fc4, [0x0389, 0x0345, 0x0000]), (0x1fc7, [0x0397, 0x0342, 0x0345]),
1193                    (0x1ff2, [0x1ffa, 0x0345, 0x0000]), (0x1ff4, [0x038f, 0x0345, 0x0000]),
1194                    (0x1ff7, [0x03a9, 0x0342, 0x0345]), (0xfb00, [0x0046, 0x0066, 0x0000]),
1195                    (0xfb01, [0x0046, 0x0069, 0x0000]), (0xfb02, [0x0046, 0x006c, 0x0000]),
1196                    (0xfb03, [0x0046, 0x0066, 0x0069]), (0xfb04, [0x0046, 0x0066, 0x006c]),
1197                    (0xfb05, [0x0053, 0x0074, 0x0000]), (0xfb06, [0x0053, 0x0074, 0x0000]),
1198                    (0xfb13, [0x0544, 0x0576, 0x0000]), (0xfb14, [0x0544, 0x0565, 0x0000]),
1199                    (0xfb15, [0x0544, 0x056b, 0x0000]), (0xfb16, [0x054e, 0x0576, 0x0000]),
1200                    (0xfb17, [0x0544, 0x056d, 0x0000]),
1201                ],
1202            },
1203            L2Lut {
1204                singles: &[ // 0 entries, 0 bytes
1205                ],
1206                multis: &[ // 0 entries, 0 bytes
1207                ],
1208            },
1209        ],
1210    };
1211}