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