Skip to main content

core/unicode/
unicode_data.rs

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