Skip to main content

mozjs_utf16_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::Utf16CharsWithTrie;
21use core::iter::FusedIterator;
22
23use icu_collections::codepointtrie::AbstractCodePointTrie;
24use icu_collections::codepointtrie::TrieValue;
25use icu_collections::codepointtrie::WithTrie;
26
27/// An iterator over the [`char`]s  and their positions.
28#[derive(Debug)]
29#[must_use = "iterators are lazy and do nothing unless consumed"]
30pub struct Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
31where
32    V: TrieValue,
33    T: AbstractCodePointTrie<'trie, V>,
34{
35    front_offset: usize,
36    iter: Utf16CharsWithTrie<'slice, 'trie, T, V>,
37}
38
39impl<'slice, 'trie, T, V> Clone for Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
40where
41    V: TrieValue,
42    T: AbstractCodePointTrie<'trie, V>,
43{
44    #[inline]
45    fn clone(&self) -> Self {
46        Self {
47            front_offset: self.front_offset,
48            iter: self.iter.clone(),
49        }
50    }
51}
52
53impl<'slice, 'trie, T, V> WithTrie<'trie, T, V> for Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
54where
55    V: TrieValue,
56    T: AbstractCodePointTrie<'trie, V>,
57{
58    #[inline]
59    fn trie(&self) -> &'trie T {
60        self.iter.trie()
61    }
62}
63
64impl<'slice, 'trie, T, V> Iterator for Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
65where
66    V: TrieValue,
67    T: AbstractCodePointTrie<'trie, V>,
68{
69    type Item = (usize, char, V);
70
71    #[inline]
72    fn next(&mut self) -> Option<Self::Item> {
73        let pre_len = self.as_slice().len();
74        match self.iter.next() {
75            None => None,
76            Some((ch, v)) => {
77                let index = self.front_offset;
78                let len = self.as_slice().len();
79                self.front_offset += pre_len - len;
80                Some((index, ch, v))
81            }
82        }
83    }
84
85    #[inline]
86    fn count(self) -> usize {
87        self.iter.count()
88    }
89
90    #[inline]
91    fn size_hint(&self) -> (usize, Option<usize>) {
92        self.iter.size_hint()
93    }
94
95    #[inline]
96    fn last(mut self) -> Option<Self::Item> {
97        // No need to go through the entire string.
98        self.next_back()
99    }
100}
101
102impl<'slice, 'trie, T, V> DoubleEndedIterator for Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
103where
104    V: TrieValue,
105    T: AbstractCodePointTrie<'trie, V>,
106{
107    #[inline]
108    fn next_back(&mut self) -> Option<Self::Item> {
109        self.iter.next_back().map(|(ch, v)| {
110            let index = self.front_offset + self.as_slice().len();
111            (index, ch, v)
112        })
113    }
114}
115
116impl<'slice, 'trie, T, V> FusedIterator for Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
117where
118    V: TrieValue,
119    T: AbstractCodePointTrie<'trie, V>,
120{
121}
122
123impl<'slice, 'trie, T, V> Utf16CharIndicesWithTrie<'slice, 'trie, T, V>
124where
125    V: TrieValue,
126    T: AbstractCodePointTrie<'trie, V>,
127{
128    #[inline(always)]
129    /// Creates the iterator from a `u16` slice.
130    pub fn new(code_units: &'slice [u16], trie: &'trie T) -> Self {
131        Self {
132            front_offset: 0,
133            iter: Utf16CharsWithTrie::new(code_units, trie),
134        }
135    }
136
137    /// Views the underlying data as a subslice of the original data.
138    ///
139    /// This has the same lifetime as the original slice, and so the
140    /// iterator can continue to be used while this exists.
141    #[must_use]
142    #[inline]
143    pub fn as_slice(&self) -> &'slice [u16] {
144        self.iter.as_slice()
145    }
146
147    /// Returns the code unit position of the next character, or the length
148    /// of the underlying string if there are no more characters.
149    ///
150    /// # Examples
151    ///
152    /// ```
153    /// use utf16_iter::Utf16CharsEx;
154    /// let mut chars = [0xD83Eu16, 0xDD73u16, 0x697Du16].char_indices();
155    ///
156    /// assert_eq!(chars.offset(), 0);
157    /// assert_eq!(chars.next(), Some((0, '🥳')));
158    ///
159    /// assert_eq!(chars.offset(), 2);
160    /// assert_eq!(chars.next(), Some((2, '楽')));
161    ///
162    /// assert_eq!(chars.offset(), 3);
163    /// assert_eq!(chars.next(), None);
164    /// ```
165    #[inline]
166    #[must_use]
167    pub fn offset(&self) -> usize {
168        self.front_offset
169    }
170}