Skip to main content

utf8_iter/
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 crate::CharsWithHandler;
21use crate::Utf8CharsWithHandler;
22use crate::Utf8Handler;
23use core::iter::FusedIterator;
24
25/// An iterator over the [`char`]s  and their positions.
26#[derive(#[automatically_derived]impl<'a, H: ::core::fmt::Debug> ::core::fmt::Debug for
    Utf8CharIndicesWithHandler<'a, H> where H: Utf8Handler {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "Utf8CharIndicesWithHandler front_offset iter",
            &self.front_offset, &&self.iter)
    }
}Debug)]
27#[must_use = "iterators are lazy and do nothing unless consumed"]
28pub struct Utf8CharIndicesWithHandler<'a, H>
29where
30    H: Utf8Handler,
31{
32    front_offset: usize,
33    iter: Utf8CharsWithHandler<'a, H>,
34}
35
36impl<'a, H> Iterator for Utf8CharIndicesWithHandler<'a, H>
37where
38    H: Utf8Handler,
39{
40    type Item = (usize, H::Output);
41
42    #[inline(always)]
43    fn next(&mut self) -> Option<(usize, H::Output)> {
44        let pre_len = self.as_slice().len();
45        match self.iter.next() {
46            None => None,
47            Some(ch) => {
48                let index = self.front_offset;
49                let len = self.as_slice().len();
50                self.front_offset += pre_len - len;
51                Some((index, ch))
52            }
53        }
54    }
55
56    #[inline(always)]
57    fn count(self) -> usize {
58        self.iter.count()
59    }
60
61    #[inline(always)]
62    fn size_hint(&self) -> (usize, Option<usize>) {
63        self.iter.size_hint()
64    }
65
66    #[inline(always)]
67    fn last(mut self) -> Option<(usize, H::Output)> {
68        // No need to go through the entire string.
69        self.next_back()
70    }
71}
72
73impl<'a, H> DoubleEndedIterator for Utf8CharIndicesWithHandler<'a, H>
74where
75    H: Utf8Handler,
76{
77    #[inline(always)]
78    fn next_back(&mut self) -> Option<(usize, H::Output)> {
79        self.iter.next_back().map(|ch| {
80            let index = self.front_offset + self.as_slice().len();
81            (index, ch)
82        })
83    }
84}
85
86impl<H> FusedIterator for Utf8CharIndicesWithHandler<'_, H> where H: Utf8Handler {}
87
88impl<'a, H> Clone for Utf8CharIndicesWithHandler<'a, H>
89where
90    H: Utf8Handler + Clone,
91{
92    fn clone(&self) -> Self {
93        Self {
94            front_offset: self.front_offset,
95            iter: self.iter.clone(),
96        }
97    }
98}
99
100impl<'a, H> Utf8CharIndicesWithHandler<'a, H>
101where
102    H: Utf8Handler,
103{
104    #[inline(always)]
105    /// Creates the iterator from a byte slice and handler.
106    pub fn new(bytes: &'a [u8], handler: H) -> Self {
107        Utf8CharIndicesWithHandler::<'a> {
108            front_offset: 0,
109            iter: Utf8CharsWithHandler::new(bytes, handler),
110        }
111    }
112
113    /// Views the underlying data as a subslice of the original data.
114    ///
115    /// This has the same lifetime as the original slice, and so the
116    /// iterator can continue to be used while this exists.
117    #[must_use]
118    #[inline(always)]
119    pub fn as_slice(&self) -> &'a [u8] {
120        self.iter.as_slice()
121    }
122
123    /// Obtains a reference to the handler.
124    #[inline(always)]
125    pub fn handler(&self) -> &H {
126        self.iter.handler()
127    }
128
129    /// Returns the byte position of the next character, or the length
130    /// of the underlying string if there are no more characters.
131    #[inline(always)]
132    #[must_use]
133    pub fn offset(&self) -> usize {
134        self.front_offset
135    }
136}
137
138// ---
139
140/// An iterator over the [`char`]s  and their positions.
141#[derive(#[automatically_derived]impl<'a, H: ::core::fmt::Debug> ::core::fmt::Debug for
    CharIndicesWithHandler<'a, H> where H: Utf8Handler {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "CharIndicesWithHandler front_offset iter", &self.front_offset,
            &&self.iter)
    }
}Debug)]
142#[must_use = "iterators are lazy and do nothing unless consumed"]
143pub struct CharIndicesWithHandler<'a, H>
144where
145    H: Utf8Handler,
146{
147    front_offset: usize,
148    iter: CharsWithHandler<'a, H>,
149}
150
151impl<'a, H> Iterator for CharIndicesWithHandler<'a, H>
152where
153    H: Utf8Handler,
154{
155    type Item = (usize, H::Output);
156
157    #[inline(always)]
158    fn next(&mut self) -> Option<(usize, H::Output)> {
159        let pre_len = self.as_str().len();
160        match self.iter.next() {
161            None => None,
162            Some(ch) => {
163                let index = self.front_offset;
164                let len = self.as_str().len();
165                self.front_offset += pre_len - len;
166                Some((index, ch))
167            }
168        }
169    }
170
171    #[inline(always)]
172    fn count(self) -> usize {
173        self.iter.count()
174    }
175
176    #[inline(always)]
177    fn size_hint(&self) -> (usize, Option<usize>) {
178        self.iter.size_hint()
179    }
180
181    #[inline(always)]
182    fn last(mut self) -> Option<(usize, H::Output)> {
183        // No need to go through the entire string.
184        self.next_back()
185    }
186}
187
188impl<'a, H> DoubleEndedIterator for CharIndicesWithHandler<'a, H>
189where
190    H: Utf8Handler,
191{
192    #[inline(always)]
193    fn next_back(&mut self) -> Option<(usize, H::Output)> {
194        self.iter.next_back().map(|ch| {
195            let index = self.front_offset + self.as_str().len();
196            (index, ch)
197        })
198    }
199}
200
201impl<H> FusedIterator for CharIndicesWithHandler<'_, H> where H: Utf8Handler {}
202
203impl<'a, H> Clone for CharIndicesWithHandler<'a, H>
204where
205    H: Utf8Handler + Clone,
206{
207    fn clone(&self) -> Self {
208        Self {
209            front_offset: self.front_offset,
210            iter: self.iter.clone(),
211        }
212    }
213}
214
215impl<'a, H> CharIndicesWithHandler<'a, H>
216where
217    H: Utf8Handler,
218{
219    #[inline(always)]
220    /// Creates the iterator from a `&str` and handler.
221    pub fn new(s: &'a str, handler: H) -> Self {
222        CharIndicesWithHandler::<'a> {
223            front_offset: 0,
224            iter: CharsWithHandler::new(s, handler),
225        }
226    }
227
228    /// Views the underlying data as a subslice of the original data.
229    ///
230    /// This has the same lifetime as the original slice, and so the
231    /// iterator can continue to be used while this exists.
232    #[must_use]
233    #[inline(always)]
234    pub fn as_str(&self) -> &'a str {
235        self.iter.as_str()
236    }
237
238    /// Obtains a reference to the handler.
239    #[inline(always)]
240    pub fn handler(&self) -> &H {
241        self.iter.handler()
242    }
243
244    /// Returns the byte position of the next character, or the length
245    /// of the underlying string if there are no more characters.
246    #[inline(always)]
247    #[must_use]
248    pub fn offset(&self) -> usize {
249        self.front_offset
250    }
251}