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.
1920use super::Utf8Chars;
21use core::iter::FusedIterator;
2223/// An iterator over the [`char`]s and their positions.
24#[derive(#[automatically_derived]
impl<'a> ::core::clone::Clone for Utf8CharIndices<'a> {
#[inline]
fn clone(&self) -> Utf8CharIndices<'a> {
Utf8CharIndices {
front_offset: ::core::clone::Clone::clone(&self.front_offset),
iter: ::core::clone::Clone::clone(&self.iter),
}
}
}Clone, #[automatically_derived]
impl<'a> ::core::fmt::Debug for Utf8CharIndices<'a> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Utf8CharIndices", "front_offset", &self.front_offset, "iter",
&&self.iter)
}
}Debug)]
25#[must_use = "iterators are lazy and do nothing unless consumed"]
26pub struct Utf8CharIndices<'a> {
27 front_offset: usize,
28 iter: Utf8Chars<'a>,
29}
3031impl<'a> Iteratorfor Utf8CharIndices<'a> {
32type Item = (usize, char);
3334#[inline]
35fn next(&mut self) -> Option<(usize, char)> {
36let pre_len = self.as_slice().len();
37match self.iter.next() {
38None => None,
39Some(ch) => {
40let index = self.front_offset;
41let len = self.as_slice().len();
42self.front_offset += pre_len - len;
43Some((index, ch))
44 }
45 }
46 }
4748#[inline]
49fn count(self) -> usize {
50self.iter.count()
51 }
5253#[inline]
54fn size_hint(&self) -> (usize, Option<usize>) {
55self.iter.size_hint()
56 }
5758#[inline]
59fn last(mut self) -> Option<(usize, char)> {
60// No need to go through the entire string.
61self.next_back()
62 }
63}
6465impl<'a> DoubleEndedIteratorfor Utf8CharIndices<'a> {
66#[inline]
67fn next_back(&mut self) -> Option<(usize, char)> {
68self.iter.next_back().map(|ch| {
69let index = self.front_offset + self.as_slice().len();
70 (index, ch)
71 })
72 }
73}
7475impl FusedIteratorfor Utf8CharIndices<'_> {}
7677impl<'a> Utf8CharIndices<'a> {
78#[inline(always)]
79/// Creates the iterator from a byte slice.
80pub fn new(bytes: &'a [u8]) -> Self {
81Utf8CharIndices::<'a> {
82 front_offset: 0,
83 iter: Utf8Chars::new(bytes),
84 }
85 }
8687/// Views the underlying data as a subslice of the original data.
88 ///
89 /// This has the same lifetime as the original slice, and so the
90 /// iterator can continue to be used while this exists.
91#[must_use]
92 #[inline]
93pub fn as_slice(&self) -> &'a [u8] {
94self.iter.as_slice()
95 }
9697/// Returns the byte position of the next character, or the length
98 /// of the underlying string if there are no more characters.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use utf8_iter::Utf8CharsEx;
104 /// let mut chars = "a楽".as_bytes().char_indices();
105 ///
106 /// assert_eq!(chars.offset(), 0);
107 /// assert_eq!(chars.next(), Some((0, 'a')));
108 ///
109 /// assert_eq!(chars.offset(), 1);
110 /// assert_eq!(chars.next(), Some((1, '楽')));
111 ///
112 /// assert_eq!(chars.offset(), 4);
113 /// assert_eq!(chars.next(), None);
114 /// ```
115#[inline]
116 #[must_use]
117pub fn offset(&self) -> usize {
118self.front_offset
119 }
120}