raw_string/str/
utf8chunks.rs1use std::iter::FusedIterator;
2use std::str::{from_utf8, from_utf8_unchecked};
3
4pub struct Utf8ChunksIter<'a> {
8 pub(super) bytes: &'a [u8],
9}
10
11pub struct Utf8Chunk<'a> {
13 pub valid: &'a str,
17
18 pub broken: &'a [u8],
24}
25
26impl<'a> Iterator for Utf8ChunksIter<'a> {
27 type Item = Utf8Chunk<'a>;
28
29 fn next(&mut self) -> Option<Utf8Chunk<'a>> {
30 if self.bytes.is_empty() {
31 return None;
32 }
33 match from_utf8(self.bytes) {
34 Ok(s) => {
35 self.bytes = &self.bytes[s.len()..];
36 Some(Utf8Chunk {
37 valid: s,
38 broken: &self.bytes[..0],
39 })
40 }
41 Err(e) => {
42 let (valid, rest) = self.bytes.split_at(e.valid_up_to());
43 let valid = unsafe { from_utf8_unchecked(valid) };
44 let (broken, rest) = rest.split_at(e.error_len().unwrap_or(rest.len()));
45 self.bytes = rest;
46 Some(Utf8Chunk { valid, broken })
47 }
48 }
49 }
50
51 #[inline]
52 fn size_hint(&self) -> (usize, Option<usize>) {
53 if self.bytes.is_empty() {
54 (0, Some(0))
55 } else {
56 (1, None)
57 }
58 }
59}
60
61impl<'a> FusedIterator for Utf8ChunksIter<'a> {}