Skip to main content

mozjs_utf8_iter/
cptrie.rs

1// Copyright Mozilla Foundation
2//
3// Licensed under the Apache License (Version 2.0), or the MIT license,
4// (the "Licenses") at your option. You may not use this file except in
5// compliance with one of the Licenses. You may obtain copies of the
6// Licenses at:
7//
8//    https://www.apache.org/licenses/LICENSE-2.0
9//    https://opensource.org/licenses/MIT
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the Licenses is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the Licenses for the specific language governing permissions and
15// limitations under the Licenses.
16
17use crate::in_inclusive_range8;
18use crate::Utf8CharIndicesWithTrie;
19use crate::UTF8_DATA;
20use core::iter::FusedIterator;
21use core::marker::PhantomData;
22use icu_collections::codepointtrie::AbstractCodePointTrie;
23use icu_collections::codepointtrie::TrieValue;
24use icu_collections::codepointtrie::WithTrie;
25
26/// Iterator by `char` and `icu_collections::codepointtrie::TrieValue`
27/// over `&[u8]` that contains potentially-invalid UTF-8. See the
28/// crate documentation.
29#[derive(Debug)]
30pub struct Utf8CharsWithTrie<'slice, 'trie, T, V>
31where
32    V: TrieValue,
33    T: AbstractCodePointTrie<'trie, V>,
34{
35    remaining: &'slice [u8],
36    trie: &'trie T,
37    phantom: PhantomData<V>,
38}
39
40impl<'slice, 'trie, T, V> Utf8CharsWithTrie<'slice, 'trie, T, V>
41where
42    V: TrieValue,
43    T: AbstractCodePointTrie<'trie, V>,
44{
45    #[inline(always)]
46    /// Creates the iterator from a byte slice.
47    pub fn new(bytes: &'slice [u8], trie: &'trie T) -> Self {
48        Self {
49            remaining: bytes,
50            trie,
51            phantom: PhantomData,
52        }
53    }
54
55    /// Views the current remaining data in the iterator as a subslice
56    /// of the original slice.
57    #[inline(always)]
58    pub fn as_slice(&self) -> &'slice [u8] {
59        self.remaining
60    }
61
62    #[inline(never)]
63    fn next_fallback(&mut self) -> Option<(char, V)> {
64        if self.remaining.is_empty() {
65            return None;
66        }
67        let first = self.remaining[0];
68        if first < 0x80 {
69            self.remaining = &self.remaining[1..];
70            // SAFETY: We just checked the precondition of `ascii()` above.
71            return Some((char::from(first), unsafe { self.trie.ascii(first) }));
72        }
73        if !in_inclusive_range8(first, 0xC2, 0xF4) || self.remaining.len() == 1 {
74            self.remaining = &self.remaining[1..];
75            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
76        }
77        let second = self.remaining[1];
78        let (lower_bound, upper_bound) = match first {
79            0xE0 => (0xA0, 0xBF),
80            0xED => (0x80, 0x9F),
81            0xF0 => (0x90, 0xBF),
82            0xF4 => (0x80, 0x8F),
83            _ => (0x80, 0xBF),
84        };
85        if !in_inclusive_range8(second, lower_bound, upper_bound) {
86            self.remaining = &self.remaining[1..];
87            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
88        }
89        if first < 0xE0 {
90            self.remaining = &self.remaining[2..];
91            let high_five = u32::from(first) & 0b11_111;
92            let low_six = u32::from(second) & 0b111_111;
93            // SAFETY: `high_five` and `low_six` conform to the
94            // precondition of `utf8_two_byte` by construction.
95            let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
96            let point = (high_five << 6) | low_six;
97            // SAFETY: `point` is in the scalar value range, because
98            // we've checked that `first` is a valid lead byte and
99            // we've then masked five bits from `first` and six bits
100            // from `second`.
101            return Some((unsafe { char::from_u32_unchecked(point) }, v));
102        }
103        if self.remaining.len() == 2 {
104            self.remaining = &self.remaining[2..];
105            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
106        }
107        let third = self.remaining[2];
108        if !in_inclusive_range8(third, 0x80, 0xBF) {
109            self.remaining = &self.remaining[2..];
110            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
111        }
112        if first < 0xF0 {
113            self.remaining = &self.remaining[3..];
114            let high_ten = ((u32::from(first) & 0b1111) << 6) | (u32::from(second) & 0b111_111);
115            let low_six = u32::from(third) & 0b111_111;
116            // SAFETY: `high_ten` and `low_six` conform to the
117            // precondition of `utf8_three_byte` by construction.
118            let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
119            let point = (high_ten << 6) | low_six;
120            // SAFETY: `point` is in the scalar value range, because
121            // we've checked that `first` is a valid lead byte and
122            // we've then masked four bits from `first` and six bits
123            // from both `second` and `third`.
124            return Some((unsafe { char::from_u32_unchecked(point) }, v));
125        }
126        // At this point, we have a valid 3-byte prefix of a
127        // four-byte sequence that has to be incomplete, because
128        // otherwise `next()` would have succeeded.
129        self.remaining = &self.remaining[3..];
130        Some(('\u{FFFD}', self.trie.bmp(0xFFFD)))
131    }
132}
133
134impl<'slice, 'trie, T, V> Clone for Utf8CharsWithTrie<'slice, 'trie, T, V>
135where
136    V: TrieValue,
137    T: AbstractCodePointTrie<'trie, V>,
138{
139    #[inline]
140    fn clone(&self) -> Self {
141        Self {
142            remaining: self.remaining,
143            trie: self.trie,
144            phantom: PhantomData,
145        }
146    }
147}
148
149impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for Utf8CharsWithTrie<'slice, 'trie, T, V>
150where
151    V: TrieValue,
152    T: AbstractCodePointTrie<'trie, V>,
153{
154    #[inline]
155    fn trie(&self) -> &'trie T {
156        self.trie
157    }
158}
159
160impl<'slice, 'trie, T, V> Iterator for Utf8CharsWithTrie<'slice, 'trie, T, V>
161where
162    V: TrieValue,
163    T: AbstractCodePointTrie<'trie, V>,
164{
165    type Item = (char, V);
166
167    #[inline]
168    fn next(&mut self) -> Option<Self::Item> {
169        // This loop is only broken out of as goto forward
170        #[allow(clippy::never_loop)]
171        loop {
172            if self.remaining.len() < 4 {
173                break;
174            }
175            let first = self.remaining[0];
176            if first < 0x80 {
177                self.remaining = &self.remaining[1..];
178                // SAFETY: We just checked the precondition of `ascii()` above.
179                return Some((char::from(first), unsafe { self.trie.ascii(first) }));
180            }
181            let second = self.remaining[1];
182            if in_inclusive_range8(first, 0xC2, 0xDF) {
183                if !in_inclusive_range8(second, 0x80, 0xBF) {
184                    break;
185                }
186                self.remaining = &self.remaining[2..];
187                let high_five = u32::from(first) & 0b11_111;
188                let low_six = u32::from(second) & 0b111_111;
189                // SAFETY: `high_five` and `low_six` conform to the
190                // precondition of `utf8_two_byte` by construction.
191                let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
192                let point = (high_five << 6) | low_six;
193                // SAFETY: `point` is in the scalar value range, because
194                // we've checked that `first` is a valid lead byte and
195                // we've then masked five bits from `first` and six bits
196                // from `second`.
197                return Some((unsafe { char::from_u32_unchecked(point) }, v));
198            }
199            // This table-based formulation was benchmark-based in encoding_rs,
200            // but it hasn't been re-benchmarked in this iterator context.
201            let third = self.remaining[2];
202            if first < 0xF0 {
203                if ((UTF8_DATA.table[usize::from(second)]
204                    & UTF8_DATA.table[usize::from(first) + 0x80])
205                    | (third >> 6))
206                    != 2
207                {
208                    break;
209                }
210                self.remaining = &self.remaining[3..];
211                let high_ten = ((u32::from(first) & 0b1111) << 6) | (u32::from(second) & 0b111_111);
212                let low_six = u32::from(third) & 0b111_111;
213                // SAFETY: `high_ten` and `low_six` conform to the
214                // precondition of `utf8_three_byte` by construction.
215                let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
216                let point = (high_ten << 6) | low_six;
217                // SAFETY: `point` is in the scalar value range, because
218                // we've checked that `first` is a valid lead byte and
219                // we've then masked four bits from `first` and six bits
220                // from both `second` and `third`.
221                return Some((unsafe { char::from_u32_unchecked(point) }, v));
222            }
223            let fourth = self.remaining[3];
224            if (u16::from(
225                UTF8_DATA.table[usize::from(second)] & UTF8_DATA.table[usize::from(first) + 0x80],
226            ) | u16::from(third >> 6)
227                | (u16::from(fourth & 0xC0) << 2))
228                != 0x202
229            {
230                break;
231            }
232            let point = ((u32::from(first) & 0x7) << 18)
233                | ((u32::from(second) & 0x3F) << 12)
234                | ((u32::from(third) & 0x3F) << 6)
235                | (u32::from(fourth) & 0x3F);
236            self.remaining = &self.remaining[4..];
237            // SAFETY: We've validated that `first` is a valid four-byte lead,
238            // taken 3 low bits from it, and six low bits from each trail.
239            return Some((
240                unsafe { char::from_u32_unchecked(point) },
241                self.trie.supplementary(point),
242            ));
243        }
244        self.next_fallback()
245    }
246}
247
248impl<'slice, 'trie, T, V> DoubleEndedIterator for Utf8CharsWithTrie<'slice, 'trie, T, V>
249where
250    V: TrieValue,
251    T: AbstractCodePointTrie<'trie, V>,
252{
253    #[inline]
254    fn next_back(&mut self) -> Option<(char, V)> {
255        if self.remaining.is_empty() {
256            return None;
257        }
258        let mut attempt = 1;
259        for b in self.remaining.iter().rev() {
260            if b & 0xC0 != 0x80 {
261                let (head, tail) = self.remaining.split_at(self.remaining.len() - attempt);
262                let mut inner = Utf8CharsWithTrie::new(tail, self.trie);
263                let candidate = inner.next();
264                if inner.as_slice().is_empty() {
265                    self.remaining = head;
266                    return candidate;
267                }
268                break;
269            }
270            if attempt == 4 {
271                break;
272            }
273            attempt += 1;
274        }
275
276        self.remaining = &self.remaining[..self.remaining.len() - 1];
277        Some(('\u{FFFD}', self.trie.bmp(0xFFFD)))
278    }
279}
280
281impl<'slice, 'trie, T, V> FusedIterator for Utf8CharsWithTrie<'slice, 'trie, T, V>
282where
283    V: TrieValue,
284    T: AbstractCodePointTrie<'trie, V>,
285{
286}
287
288/// Convenience trait that adds `chars_with_trie()` and `char_indices_with_trie()` methods
289/// similar to the ones `icu_collections::codepointtrie::CharsWithTrieEx` adds to string
290/// slices to `u8` slices.
291pub trait Utf8CharsWithTrieEx<'slice, 'trie, T, V>
292where
293    V: TrieValue,
294    T: AbstractCodePointTrie<'trie, V>,
295{
296    /// Convenience method for creating an UTF-16 iterator
297    /// with trie values for the slice.
298    fn chars_with_trie(&'slice self, trie: &'trie T) -> Utf8CharsWithTrie<'slice, 'trie, T, V>;
299    /// Convenience method for creating a code unit index and
300    /// UTF-16 iterator with trie values for the slice.
301    fn char_indices_with_trie(
302        &'slice self,
303        trie: &'trie T,
304    ) -> Utf8CharIndicesWithTrie<'slice, 'trie, T, V>;
305}
306
307impl<'slice, 'trie, T, V> Utf8CharsWithTrieEx<'slice, 'trie, T, V> for [u8]
308where
309    V: TrieValue,
310    T: AbstractCodePointTrie<'trie, V>,
311{
312    /// Convenience method for creating an UTF-16 iterator
313    /// with trie values for the slice.
314    #[inline]
315    fn chars_with_trie(&'slice self, trie: &'trie T) -> Utf8CharsWithTrie<'slice, 'trie, T, V> {
316        Utf8CharsWithTrie::new(self, trie)
317    }
318
319    /// Convenience method for creating a code unit index and
320    /// UTF-16 iterator with trie values for the slice.
321    #[inline]
322    fn char_indices_with_trie(
323        &'slice self,
324        trie: &'trie T,
325    ) -> Utf8CharIndicesWithTrie<'slice, 'trie, T, V> {
326        Utf8CharIndicesWithTrie::new(self, trie)
327    }
328}
329
330// --
331
332/// Iterator by `char` and `icu_collections::codepointtrie::TrieValue`
333/// over `&[u8]` that contains potentially-invalid UTF-8. Uses `V::default()`
334/// for ASCII instead of reading from the trie. See the
335/// crate documentation.
336#[derive(Debug)]
337pub struct Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
338where
339    V: TrieValue + Default,
340    T: AbstractCodePointTrie<'trie, V>,
341{
342    remaining: &'slice [u8],
343    trie: &'trie T,
344    phantom: PhantomData<V>,
345}
346
347impl<'slice, 'trie, T, V> Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
348where
349    V: TrieValue + Default,
350    T: AbstractCodePointTrie<'trie, V>,
351{
352    #[inline(always)]
353    /// Creates the iterator from a byte slice.
354    pub fn new(bytes: &'slice [u8], trie: &'trie T) -> Self {
355        Self {
356            remaining: bytes,
357            trie,
358            phantom: PhantomData,
359        }
360    }
361
362    /// Views the current remaining data in the iterator as a subslice
363    /// of the original slice.
364    #[inline(always)]
365    pub fn as_slice(&self) -> &'slice [u8] {
366        self.remaining
367    }
368
369    #[inline(never)]
370    fn next_fallback(&mut self) -> Option<(char, V)> {
371        if self.remaining.is_empty() {
372            return None;
373        }
374        let first = self.remaining[0];
375        if first < 0x80 {
376            self.remaining = &self.remaining[1..];
377            return Some((char::from(first), V::default()));
378        }
379        if !in_inclusive_range8(first, 0xC2, 0xF4) || self.remaining.len() == 1 {
380            self.remaining = &self.remaining[1..];
381            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
382        }
383        let second = self.remaining[1];
384        let (lower_bound, upper_bound) = match first {
385            0xE0 => (0xA0, 0xBF),
386            0xED => (0x80, 0x9F),
387            0xF0 => (0x90, 0xBF),
388            0xF4 => (0x80, 0x8F),
389            _ => (0x80, 0xBF),
390        };
391        if !in_inclusive_range8(second, lower_bound, upper_bound) {
392            self.remaining = &self.remaining[1..];
393            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
394        }
395        if first < 0xE0 {
396            self.remaining = &self.remaining[2..];
397            let high_five = u32::from(first) & 0b11_111;
398            let low_six = u32::from(second) & 0b111_111;
399            // SAFETY: `high_five` and `low_six` conform to the
400            // precondition of `utf8_two_byte` by construction.
401            let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
402            let point = (high_five << 6) | low_six;
403            // SAFETY: `point` is in the scalar value range, because
404            // we've checked that `first` is a valid lead byte and
405            // we've then masked five bits from `first` and six bits
406            // from `second`.
407            return Some((unsafe { char::from_u32_unchecked(point) }, v));
408        }
409        if self.remaining.len() == 2 {
410            self.remaining = &self.remaining[2..];
411            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
412        }
413        let third = self.remaining[2];
414        if !in_inclusive_range8(third, 0x80, 0xBF) {
415            self.remaining = &self.remaining[2..];
416            return Some(('\u{FFFD}', self.trie.bmp(0xFFFD)));
417        }
418        if first < 0xF0 {
419            self.remaining = &self.remaining[3..];
420            let high_ten = ((u32::from(first) & 0b1111) << 6) | (u32::from(second) & 0b111_111);
421            let low_six = u32::from(third) & 0b111_111;
422            // SAFETY: `high_ten` and `low_six` conform to the
423            // precondition of `utf8_three_byte` by construction.
424            let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
425            let point = (high_ten << 6) | low_six;
426            // SAFETY: `point` is in the scalar value range, because
427            // we've checked that `first` is a valid lead byte and
428            // we've then masked four bits from `first` and six bits
429            // from both `second` and `third`.
430            return Some((unsafe { char::from_u32_unchecked(point) }, v));
431        }
432        // At this point, we have a valid 3-byte prefix of a
433        // four-byte sequence that has to be incomplete, because
434        // otherwise `next()` would have succeeded.
435        self.remaining = &self.remaining[3..];
436        Some(('\u{FFFD}', self.trie.bmp(0xFFFD)))
437    }
438}
439
440impl<'slice, 'trie, T, V> Clone for Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
441where
442    V: TrieValue + Default,
443    T: AbstractCodePointTrie<'trie, V>,
444{
445    #[inline]
446    fn clone(&self) -> Self {
447        Self {
448            remaining: self.remaining,
449            trie: self.trie,
450            phantom: PhantomData,
451        }
452    }
453}
454
455impl<'slice, 'trie, T, V> WithTrie<'trie, T, V>
456    for Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
457where
458    V: TrieValue + Default,
459    T: AbstractCodePointTrie<'trie, V>,
460{
461    #[inline]
462    fn trie(&self) -> &'trie T {
463        self.trie
464    }
465}
466
467impl<'slice, 'trie, T, V> Iterator for Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
468where
469    V: TrieValue + Default,
470    T: AbstractCodePointTrie<'trie, V>,
471{
472    type Item = (char, V);
473
474    #[inline]
475    fn next(&mut self) -> Option<Self::Item> {
476        // This loop is only broken out of as goto forward
477        #[allow(clippy::never_loop)]
478        loop {
479            if self.remaining.len() < 4 {
480                break;
481            }
482            let first = self.remaining[0];
483            if first < 0x80 {
484                self.remaining = &self.remaining[1..];
485                return Some((char::from(first), V::default()));
486            }
487            let second = self.remaining[1];
488            if in_inclusive_range8(first, 0xC2, 0xDF) {
489                if !in_inclusive_range8(second, 0x80, 0xBF) {
490                    break;
491                }
492                self.remaining = &self.remaining[2..];
493                let high_five = u32::from(first) & 0b11_111;
494                let low_six = u32::from(second) & 0b111_111;
495                // SAFETY: `high_five` and `low_six` conform to the
496                // precondition of `utf8_two_byte` by construction.
497                let v = unsafe { self.trie.utf8_two_byte(high_five, low_six) };
498                let point = (high_five << 6) | low_six;
499                // SAFETY: `point` is in the scalar value range, because
500                // we've checked that `first` is a valid lead byte and
501                // we've then masked five bits from `first` and six bits
502                // from `second`.
503                return Some((unsafe { char::from_u32_unchecked(point) }, v));
504            }
505            // This table-based formulation was benchmark-based in encoding_rs,
506            // but it hasn't been re-benchmarked in this iterator context.
507            let third = self.remaining[2];
508            if first < 0xF0 {
509                if ((UTF8_DATA.table[usize::from(second)]
510                    & UTF8_DATA.table[usize::from(first) + 0x80])
511                    | (third >> 6))
512                    != 2
513                {
514                    break;
515                }
516                self.remaining = &self.remaining[3..];
517                let high_ten = ((u32::from(first) & 0b1111) << 6) | (u32::from(second) & 0b111_111);
518                let low_six = u32::from(third) & 0b111_111;
519                // SAFETY: `high_ten` and `low_six` conform to the
520                // precondition of `utf8_three_byte` by construction.
521                let v = unsafe { self.trie.utf8_three_byte(high_ten, low_six) };
522                let point = (high_ten << 6) | low_six;
523                // SAFETY: `point` is in the scalar value range, because
524                // we've checked that `first` is a valid lead byte and
525                // we've then masked four bits from `first` and six bits
526                // from both `second` and `third`.
527                return Some((unsafe { char::from_u32_unchecked(point) }, v));
528            }
529            let fourth = self.remaining[3];
530            if (u16::from(
531                UTF8_DATA.table[usize::from(second)] & UTF8_DATA.table[usize::from(first) + 0x80],
532            ) | u16::from(third >> 6)
533                | (u16::from(fourth & 0xC0) << 2))
534                != 0x202
535            {
536                break;
537            }
538            let point = ((u32::from(first) & 0x7) << 18)
539                | ((u32::from(second) & 0x3F) << 12)
540                | ((u32::from(third) & 0x3F) << 6)
541                | (u32::from(fourth) & 0x3F);
542            self.remaining = &self.remaining[4..];
543            // SAFETY: We've validated that `first` is a valid four-byte lead,
544            // taken 3 low bits from it, and six low bits from each trail.
545            return Some((
546                unsafe { char::from_u32_unchecked(point) },
547                self.trie.supplementary(point),
548            ));
549        }
550        self.next_fallback()
551    }
552}
553
554impl<'slice, 'trie, T, V> DoubleEndedIterator
555    for Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
556where
557    V: TrieValue + Default,
558    T: AbstractCodePointTrie<'trie, V>,
559{
560    #[inline]
561    fn next_back(&mut self) -> Option<(char, V)> {
562        if self.remaining.is_empty() {
563            return None;
564        }
565        let mut attempt = 1;
566        for b in self.remaining.iter().rev() {
567            if b & 0xC0 != 0x80 {
568                let (head, tail) = self.remaining.split_at(self.remaining.len() - attempt);
569                let mut inner = Utf8CharsWithTrieDefaultForAscii::new(tail, self.trie);
570                let candidate = inner.next();
571                if inner.as_slice().is_empty() {
572                    self.remaining = head;
573                    return candidate;
574                }
575                break;
576            }
577            if attempt == 4 {
578                break;
579            }
580            attempt += 1;
581        }
582
583        self.remaining = &self.remaining[..self.remaining.len() - 1];
584        Some(('\u{FFFD}', self.trie.bmp(0xFFFD)))
585    }
586}
587
588impl<'slice, 'trie, T, V> FusedIterator for Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>
589where
590    V: TrieValue + Default,
591    T: AbstractCodePointTrie<'trie, V>,
592{
593}
594
595/// Convenience trait that adds `chars_with_trie_default_for_ascii()` and `char_indices_with_trie_default_for_ascii()` methods
596/// similar to the ones `icu_collections::codepointtrie::CharsWithTrieEx` adds to string
597/// slices to `u8` slices.
598pub trait Utf8CharsWithTrieDefaultForAsciiEx<'slice, 'trie, T, V>
599where
600    V: TrieValue + Default,
601    T: AbstractCodePointTrie<'trie, V>,
602{
603    /// Convenience method for creating an UTF-16 iterator
604    /// with trie values for the slice.
605    fn chars_with_trie_default_for_ascii(
606        &'slice self,
607        trie: &'trie T,
608    ) -> Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>;
609    /// Convenience method for creating a code unit index and
610    /// UTF-16 iterator with trie values for the slice.
611    fn char_indices_with_trie_default_for_ascii(
612        &'slice self,
613        trie: &'trie T,
614    ) -> Utf8CharIndicesWithTrie<'slice, 'trie, T, V>;
615}
616
617impl<'slice, 'trie, T, V> Utf8CharsWithTrieDefaultForAsciiEx<'slice, 'trie, T, V> for [u8]
618where
619    V: TrieValue + Default,
620    T: AbstractCodePointTrie<'trie, V>,
621{
622    /// Convenience method for creating an UTF-16 iterator
623    /// with trie values for the slice.
624    #[inline]
625    fn chars_with_trie_default_for_ascii(
626        &'slice self,
627        trie: &'trie T,
628    ) -> Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V> {
629        Utf8CharsWithTrieDefaultForAscii::new(self, trie)
630    }
631
632    /// Convenience method for creating a code unit index and
633    /// UTF-16 iterator with trie values for the slice.
634    #[inline]
635    fn char_indices_with_trie_default_for_ascii(
636        &'slice self,
637        trie: &'trie T,
638    ) -> Utf8CharIndicesWithTrie<'slice, 'trie, T, V> {
639        Utf8CharIndicesWithTrie::new(self, trie)
640    }
641}