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