/rust/registry/src/index.crates.io-6f17d22bba15001f/utf16_iter-1.0.5/src/indices.rs
Line | Count | Source (jump to first uncovered line) |
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 | | |
20 | | use super::Utf16Chars; |
21 | | use core::iter::FusedIterator; |
22 | | |
23 | | /// An iterator over the [`char`]s and their positions. |
24 | | #[derive(Clone, Debug)] |
25 | | #[must_use = "iterators are lazy and do nothing unless consumed"] |
26 | | pub struct Utf16CharIndices<'a> { |
27 | | front_offset: usize, |
28 | | iter: Utf16Chars<'a>, |
29 | | } |
30 | | |
31 | | impl<'a> Iterator for Utf16CharIndices<'a> { |
32 | | type Item = (usize, char); |
33 | | |
34 | | #[inline] |
35 | 0 | fn next(&mut self) -> Option<(usize, char)> { |
36 | 0 | let pre_len = self.as_slice().len(); |
37 | 0 | match self.iter.next() { |
38 | 0 | None => None, |
39 | 0 | Some(ch) => { |
40 | 0 | let index = self.front_offset; |
41 | 0 | let len = self.as_slice().len(); |
42 | 0 | self.front_offset += pre_len - len; |
43 | 0 | Some((index, ch)) |
44 | | } |
45 | | } |
46 | 0 | } |
47 | | |
48 | | #[inline] |
49 | 0 | fn count(self) -> usize { |
50 | 0 | self.iter.count() |
51 | 0 | } |
52 | | |
53 | | #[inline] |
54 | 0 | fn size_hint(&self) -> (usize, Option<usize>) { |
55 | 0 | self.iter.size_hint() |
56 | 0 | } |
57 | | |
58 | | #[inline] |
59 | 0 | fn last(mut self) -> Option<(usize, char)> { |
60 | 0 | // No need to go through the entire string. |
61 | 0 | self.next_back() |
62 | 0 | } |
63 | | } |
64 | | |
65 | | impl<'a> DoubleEndedIterator for Utf16CharIndices<'a> { |
66 | | #[inline] |
67 | 0 | fn next_back(&mut self) -> Option<(usize, char)> { |
68 | 0 | self.iter.next_back().map(|ch| { |
69 | 0 | let index = self.front_offset + self.as_slice().len(); |
70 | 0 | (index, ch) |
71 | 0 | }) |
72 | 0 | } |
73 | | } |
74 | | |
75 | | impl FusedIterator for Utf16CharIndices<'_> {} |
76 | | |
77 | | impl<'a> Utf16CharIndices<'a> { |
78 | | #[inline(always)] |
79 | | /// Creates the iterator from a `u16` slice. |
80 | 0 | pub fn new(code_units: &'a [u16]) -> Self { |
81 | 0 | Utf16CharIndices::<'a> { |
82 | 0 | front_offset: 0, |
83 | 0 | iter: Utf16Chars::new(code_units), |
84 | 0 | } |
85 | 0 | } |
86 | | |
87 | | /// 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] |
93 | 0 | pub fn as_slice(&self) -> &'a [u16] { |
94 | 0 | self.iter.as_slice() |
95 | 0 | } |
96 | | |
97 | | /// Returns the code unit 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 utf16_iter::Utf16CharsEx; |
104 | | /// let mut chars = [0xD83Eu16, 0xDD73u16, 0x697Du16].char_indices(); |
105 | | /// |
106 | | /// assert_eq!(chars.offset(), 0); |
107 | | /// assert_eq!(chars.next(), Some((0, '🥳'))); |
108 | | /// |
109 | | /// assert_eq!(chars.offset(), 2); |
110 | | /// assert_eq!(chars.next(), Some((2, '楽'))); |
111 | | /// |
112 | | /// assert_eq!(chars.offset(), 3); |
113 | | /// assert_eq!(chars.next(), None); |
114 | | /// ``` |
115 | | #[inline] |
116 | | #[must_use] |
117 | 0 | pub fn offset(&self) -> usize { |
118 | 0 | self.front_offset |
119 | 0 | } |
120 | | } |