Skip to main content

mozjs_utf8_iter/
cptrie_indices.rs

1// The code in this file was adapted from the CharIndices implementation of
2// the Rust standard library at revision ab32548539ec38a939c1b58599249f3b54130026
3// (https://github.com/rust-lang/rust/blob/ab32548539ec38a939c1b58599249f3b54130026/library/core/src/str/iter.rs).
4//
5// Excerpt from https://github.com/rust-lang/rust/blob/ab32548539ec38a939c1b58599249f3b54130026/COPYRIGHT ,
6// which refers to
7// https://github.com/rust-lang/rust/blob/ab32548539ec38a939c1b58599249f3b54130026/LICENSE-APACHE
8// and
9// https://github.com/rust-lang/rust/blob/ab32548539ec38a939c1b58599249f3b54130026/LICENSE-MIT
10// :
11//
12// For full authorship information, see the version control history or
13// https://thanks.rust-lang.org
14//
15// Except as otherwise noted (below and/or in individual files), Rust is
16// licensed under the Apache License, Version 2.0 <LICENSE-APACHE> or
17// <http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
18// <LICENSE-MIT> or <http://opensource.org/licenses/MIT>, at your option.
19
20use super::Utf8CharsWithTrie;
21use super::Utf8CharsWithTrieDefaultForAscii;
22use core::iter::FusedIterator;
23
24use icu_collections::codepointtrie::AbstractCodePointTrie;
25use icu_collections::codepointtrie::TrieValue;
26use icu_collections::codepointtrie::WithTrie;
27
28/// An iterator over the [`char`]s  and their positions.
29#[derive(Debug)]
30#[must_use = "iterators are lazy and do nothing unless consumed"]
31pub struct Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
32where
33    V: TrieValue,
34    T: AbstractCodePointTrie<'trie, V>,
35{
36    front_offset: usize,
37    iter: Utf8CharsWithTrie<'slice, 'trie, T, V>,
38}
39
40impl<'slice, 'trie, T, V> Clone for Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
41where
42    V: TrieValue,
43    T: AbstractCodePointTrie<'trie, V>,
44{
45    #[inline]
46    fn clone(&self) -> Self {
47        Self {
48            front_offset: self.front_offset,
49            iter: self.iter.clone(),
50        }
51    }
52}
53
54impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
55where
56    V: TrieValue,
57    T: AbstractCodePointTrie<'trie, V>,
58{
59    #[inline]
60    fn trie(&self) -> &'trie T {
61        self.iter.trie()
62    }
63}
64
65impl<'slice, 'trie, T, V> Iterator for Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
66where
67    V: TrieValue,
68    T: AbstractCodePointTrie<'trie, V>,
69{
70    type Item = (usize, char, V);
71
72    #[inline]
73    fn next(&mut self) -> Option<Self::Item> {
74        let pre_len = self.as_slice().len();
75        match self.iter.next() {
76            None => None,
77            Some((ch, v)) => {
78                let index = self.front_offset;
79                let len = self.as_slice().len();
80                self.front_offset += pre_len - len;
81                Some((index, ch, v))
82            }
83        }
84    }
85
86    #[inline]
87    fn count(self) -> usize {
88        self.iter.count()
89    }
90
91    #[inline]
92    fn size_hint(&self) -> (usize, Option<usize>) {
93        self.iter.size_hint()
94    }
95
96    #[inline]
97    fn last(mut self) -> Option<Self::Item> {
98        // No need to go through the entire string.
99        self.next_back()
100    }
101}
102
103impl<'slice, 'trie, T, V> DoubleEndedIterator for Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
104where
105    V: TrieValue,
106    T: AbstractCodePointTrie<'trie, V>,
107{
108    #[inline]
109    fn next_back(&mut self) -> Option<Self::Item> {
110        self.iter.next_back().map(|(ch, v)| {
111            let index = self.front_offset + self.as_slice().len();
112            (index, ch, v)
113        })
114    }
115}
116
117impl<'slice, 'trie, T, V> FusedIterator for Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
118where
119    V: TrieValue,
120    T: AbstractCodePointTrie<'trie, V>,
121{
122}
123
124impl<'slice, 'trie, T, V> Utf8CharIndicesWithTrie<'slice, 'trie, T, V>
125where
126    V: TrieValue,
127    T: AbstractCodePointTrie<'trie, V>,
128{
129    #[inline(always)]
130    /// Creates the iterator from a `u8` slice.
131    pub fn new(code_units: &'slice [u8], trie: &'trie T) -> Self {
132        Self {
133            front_offset: 0,
134            iter: Utf8CharsWithTrie::new(code_units, trie),
135        }
136    }
137
138    /// Views the underlying data as a subslice of the original data.
139    ///
140    /// This has the same lifetime as the original slice, and so the
141    /// iterator can continue to be used while this exists.
142    #[must_use]
143    #[inline]
144    pub fn as_slice(&self) -> &'slice [u8] {
145        self.iter.as_slice()
146    }
147
148    /// Returns the code unit position of the next character, or the length
149    /// of the underlying string if there are no more characters.
150    #[inline]
151    #[must_use]
152    pub fn offset(&self) -> usize {
153        self.front_offset
154    }
155}
156
157// --
158
159/// An iterator over the [`char`]s  and their positions.
160#[derive(Debug)]
161#[must_use = "iterators are lazy and do nothing unless consumed"]
162pub struct Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
163where
164    V: TrieValue + Default,
165    T: AbstractCodePointTrie<'trie, V>,
166{
167    front_offset: usize,
168    iter: Utf8CharsWithTrieDefaultForAscii<'slice, 'trie, T, V>,
169}
170
171impl<'slice, 'trie, T, V> Clone for Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
172where
173    V: TrieValue + Default,
174    T: AbstractCodePointTrie<'trie, V>,
175{
176    #[inline]
177    fn clone(&self) -> Self {
178        Self {
179            front_offset: self.front_offset,
180            iter: self.iter.clone(),
181        }
182    }
183}
184
185impl<'slice, 'trie, T, V> WithTrie<'trie, T, V>
186    for Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
187where
188    V: TrieValue + Default,
189    T: AbstractCodePointTrie<'trie, V>,
190{
191    #[inline]
192    fn trie(&self) -> &'trie T {
193        self.iter.trie()
194    }
195}
196
197impl<'slice, 'trie, T, V> Iterator for Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
198where
199    V: TrieValue + Default,
200    T: AbstractCodePointTrie<'trie, V>,
201{
202    type Item = (usize, char, V);
203
204    #[inline]
205    fn next(&mut self) -> Option<Self::Item> {
206        let pre_len = self.as_slice().len();
207        match self.iter.next() {
208            None => None,
209            Some((ch, v)) => {
210                let index = self.front_offset;
211                let len = self.as_slice().len();
212                self.front_offset += pre_len - len;
213                Some((index, ch, v))
214            }
215        }
216    }
217
218    #[inline]
219    fn count(self) -> usize {
220        self.iter.count()
221    }
222
223    #[inline]
224    fn size_hint(&self) -> (usize, Option<usize>) {
225        self.iter.size_hint()
226    }
227
228    #[inline]
229    fn last(mut self) -> Option<Self::Item> {
230        // No need to go through the entire string.
231        self.next_back()
232    }
233}
234
235impl<'slice, 'trie, T, V> DoubleEndedIterator
236    for Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
237where
238    V: TrieValue + Default,
239    T: AbstractCodePointTrie<'trie, V>,
240{
241    #[inline]
242    fn next_back(&mut self) -> Option<Self::Item> {
243        self.iter.next_back().map(|(ch, v)| {
244            let index = self.front_offset + self.as_slice().len();
245            (index, ch, v)
246        })
247    }
248}
249
250impl<'slice, 'trie, T, V> FusedIterator
251    for Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
252where
253    V: TrieValue + Default,
254    T: AbstractCodePointTrie<'trie, V>,
255{
256}
257
258impl<'slice, 'trie, T, V> Utf8CharIndicesWithTrieDefaultForAscii<'slice, 'trie, T, V>
259where
260    V: TrieValue + Default,
261    T: AbstractCodePointTrie<'trie, V>,
262{
263    #[inline(always)]
264    /// Creates the iterator from a `u8` slice.
265    pub fn new(code_units: &'slice [u8], trie: &'trie T) -> Self {
266        Self {
267            front_offset: 0,
268            iter: Utf8CharsWithTrieDefaultForAscii::new(code_units, trie),
269        }
270    }
271
272    /// Views the underlying data as a subslice of the original data.
273    ///
274    /// This has the same lifetime as the original slice, and so the
275    /// iterator can continue to be used while this exists.
276    #[must_use]
277    #[inline]
278    pub fn as_slice(&self) -> &'slice [u8] {
279        self.iter.as_slice()
280    }
281
282    /// Returns the code unit position of the next character, or the length
283    /// of the underlying string if there are no more characters.
284    #[inline]
285    #[must_use]
286    pub fn offset(&self) -> usize {
287        self.front_offset
288    }
289}