Skip to main content

utf8_iter/
basic.rs

1// Copyright Mozilla Foundation
2//
3// Licensed under the Apache License (Version 2.0), or the MIT license,
4// (the "Licenses") at your option. You may not use this file except in
5// compliance with one of the Licenses. You may obtain copies of the
6// Licenses at:
7//
8//    https://www.apache.org/licenses/LICENSE-2.0
9//    https://opensource.org/licenses/MIT
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the Licenses is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the Licenses for the specific language governing permissions and
15// limitations under the Licenses.
16
17use utf_types::utf8::Ascii;
18use utf_types::utf8::FourByteSequence;
19use utf_types::utf8::ThreeByteSequence;
20use utf_types::utf8::TwoByteSequence;
21
22use crate::Utf8Handler;
23
24/// The basic `Output = char` case.
25///
26/// (Normally this is not particularly interesting outside the
27/// crate, but exporting this is useful for testing.)
28#[derive(#[automatically_derived]impl ::core::fmt::Debug for DefaultHandler {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "DefaultHandler")
    }
}Debug, #[automatically_derived]impl ::core::clone::Clone for DefaultHandler {
    #[inline]
    fn clone(&self) -> Self { DefaultHandler }
}Clone)]
29pub struct DefaultHandler;
30
31impl DefaultHandler {
32    /// Constructs a new `DefaultHandler`
33    pub const fn new() -> Self {
34        Self {}
35    }
36}
37
38impl Default for DefaultHandler {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl Utf8Handler for DefaultHandler {
45    type Output = char;
46
47    /// Map a single-byte UTF-8 sequence to `Output`.
48    #[inline(always)]
49    fn single_byte(&self, ascii: Ascii) -> Self::Output {
50        ascii.to_char()
51    }
52
53    /// Map a two-byte UTF-8 sequence to `Output`.
54    #[inline(always)]
55    fn two_byte(&self, sequence: TwoByteSequence) -> Self::Output {
56        sequence.to_char()
57    }
58
59    /// Map a three-byte UTF-8 sequence to `Output`.
60    #[inline(always)]
61    fn three_byte(&self, sequence: ThreeByteSequence) -> Self::Output {
62        sequence.to_char()
63    }
64
65    /// Map a four-byte UTF-8 sequence to `Output`.
66    #[inline(always)]
67    fn four_byte(&self, sequence: FourByteSequence) -> Self::Output {
68        sequence.to_char()
69    }
70
71    /// Map a single UTF-8 error to `Output`.
72    #[inline(always)]
73    fn error(&self) -> Self::Output {
74        char::REPLACEMENT_CHARACTER
75    }
76}
77
78#[doc = r" Iterator by `char` over `&[u8]` that contains"]
#[doc = r" potentially-invalid UTF-8. See the crate documentation."]
pub struct Utf8Chars<'a> {
    inner: crate::Utf8CharsWithHandler<'a, DefaultHandler>,
}
#[automatically_derived]impl<'a> ::core::fmt::Debug for Utf8Chars<'a> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "Utf8Chars inner", &&self.inner)
    }
}
impl<'a> Utf8Chars<'a> {
    #[inline(always)]
    /// Creates the iterator from a byte slice.
    pub fn new(bytes: &'a [u8]) -> Self {
        Self {
            inner: crate::Utf8CharsWithHandler::new(bytes,
                DefaultHandler::new()),
        }
    }
    /// Views the current remaining data in the iterator as a subslice
    /// of the original slice.
    #[must_use]
    #[inline(always)]
    pub fn as_slice(&self) -> &'a [u8] { self.inner.as_slice() }
}
impl<'a> Iterator for Utf8Chars<'a> {
    type Item = char;
    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> { self.inner.next() }
    #[inline(always)]
    fn count(self) -> usize { self.inner.count() }
    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
    #[inline(always)]
    fn last(mut self) -> Option<Self::Item> { self.next_back() }
}
impl<'a> DoubleEndedIterator for Utf8Chars<'a> {
    #[inline(always)]
    fn next_back(&mut self) -> Option<Self::Item> { self.inner.next_back() }
}
impl core::iter::FusedIterator for Utf8Chars<'_> {}
impl<'a> Clone for Utf8Chars<'a> {
    fn clone(&self) -> Self { Self { inner: self.inner.clone() } }
}
#[doc = r" Iterator by `char` and their indices over `&[u8]` that contains"]
#[doc = r" potentially-invalid UTF-8. See the crate documentation."]
pub struct Utf8CharIndices<'a> {
    inner: crate::Utf8CharIndicesWithHandler<'a, DefaultHandler>,
}
#[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_field1_finish(f,
            "Utf8CharIndices inner", &&self.inner)
    }
}
impl<'a> Utf8CharIndices<'a> {
    #[inline(always)]
    /// Creates the iterator from a byte slice.
    pub fn new(bytes: &'a [u8]) -> Self {
        Self {
            inner: crate::Utf8CharIndicesWithHandler::new(bytes,
                DefaultHandler::new()),
        }
    }
    /// Views the current remaining data in the iterator as a subslice
    /// of the original slice.
    #[inline(always)]
    #[must_use]
    pub fn as_slice(&self) -> &'a [u8] { self.inner.as_slice() }
    /// The current index offset
    #[inline(always)]
    #[must_use]
    pub fn offset(&self) -> usize { self.inner.offset() }
}
impl<'a> Iterator for Utf8CharIndices<'a> {
    type Item = (usize, char);
    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> { self.inner.next() }
    #[inline(always)]
    fn count(self) -> usize { self.inner.count() }
    #[inline(always)]
    fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
    #[inline(always)]
    fn last(mut self) -> Option<Self::Item> { self.next_back() }
}
impl<'a> DoubleEndedIterator for Utf8CharIndices<'a> {
    #[inline(always)]
    fn next_back(&mut self) -> Option<Self::Item> { self.inner.next_back() }
}
impl core::iter::FusedIterator for Utf8CharIndices<'_> {}
impl<'a> Clone for Utf8CharIndices<'a> {
    fn clone(&self) -> Self { Self { inner: self.inner.clone() } }
}crate::macros::named_iterators_from_no_argument_handler!(
79    DefaultHandler,
80    char,
81    /// Iterator by `char` over `&[u8]` that contains
82    /// potentially-invalid UTF-8. See the crate documentation.
83    ,
84    Utf8Chars,
85    /// Iterator by `char` and their indices over `&[u8]` that contains
86    /// potentially-invalid UTF-8. See the crate documentation.
87    ,
88    Utf8CharIndices,
89);
90
91/// Convenience trait that adds `chars()` and `char_indices()` methods
92/// similar to the ones on string slices to byte slices.
93pub trait Utf8CharsEx {
94    /// Iterator over `char`s
95    fn chars(&self) -> Utf8Chars<'_>;
96    /// Iterator over `char`s and their indices
97    fn char_indices(&self) -> Utf8CharIndices<'_>;
98}
99
100impl Utf8CharsEx for [u8] {
101    /// Convenience method for creating an UTF-8 iterator
102    /// for the slice.
103    #[inline(always)]
104    fn chars(&self) -> Utf8Chars<'_> {
105        Utf8Chars::new(self)
106    }
107    /// Convenience method for creating a byte index and
108    /// UTF-8 iterator for the slice.
109    #[inline(always)]
110    fn char_indices(&self) -> Utf8CharIndices<'_> {
111        Utf8CharIndices::new(self)
112    }
113}
114
115// No manually-written tests for forward-iteration, because the code passed multiple
116// days of fuzzing comparing with known-good behavior.