obeli_sk_boa_string/
iter.rs1use std::iter::FusedIterator;
2
3use crate::{CodePoint, JsStr};
4
5use super::JsStrVariant;
6
7#[derive(Debug, Clone)]
8enum IterInner<'a> {
9 U8(std::iter::Copied<std::slice::Iter<'a, u8>>),
10 U16(std::iter::Copied<std::slice::Iter<'a, u16>>),
11}
12
13#[derive(Debug, Clone)]
15pub struct Iter<'a> {
16 inner: IterInner<'a>,
17}
18
19impl<'a> Iter<'a> {
20 #[inline]
21 pub(crate) fn new(s: JsStr<'a>) -> Self {
22 let inner = match s.variant() {
23 JsStrVariant::Latin1(s) => IterInner::U8(s.iter().copied()),
24 JsStrVariant::Utf16(s) => IterInner::U16(s.iter().copied()),
25 };
26 Iter { inner }
27 }
28}
29
30impl Iterator for Iter<'_> {
31 type Item = u16;
32
33 #[inline]
34 fn next(&mut self) -> Option<Self::Item> {
35 match &mut self.inner {
36 IterInner::U8(iter) => iter.map(u16::from).next(),
37 IterInner::U16(iter) => iter.next(),
38 }
39 }
40}
41
42impl FusedIterator for Iter<'_> {}
43
44impl ExactSizeIterator for Iter<'_> {
45 #[inline]
46 fn len(&self) -> usize {
47 match &self.inner {
48 IterInner::U8(v) => v.len(),
49 IterInner::U16(v) => v.len(),
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
55enum WindowsInner<'a> {
56 U8(std::slice::Windows<'a, u8>),
57 U16(std::slice::Windows<'a, u16>),
58}
59
60#[derive(Debug, Clone)]
64pub struct Windows<'a> {
65 inner: WindowsInner<'a>,
66}
67
68impl<'a> Windows<'a> {
69 #[inline]
70 pub(crate) fn new(string: JsStr<'a>, size: usize) -> Self {
71 let inner = match string.variant() {
72 JsStrVariant::Latin1(v) => WindowsInner::U8(v.windows(size)),
73 JsStrVariant::Utf16(v) => WindowsInner::U16(v.windows(size)),
74 };
75 Self { inner }
76 }
77}
78
79impl<'a> Iterator for Windows<'a> {
80 type Item = JsStr<'a>;
81
82 #[inline]
83 fn next(&mut self) -> Option<Self::Item> {
84 match &mut self.inner {
85 WindowsInner::U8(iter) => iter.next().map(JsStr::latin1),
86 WindowsInner::U16(iter) => iter.next().map(JsStr::utf16),
87 }
88 }
89}
90
91impl FusedIterator for Windows<'_> {}
92
93impl ExactSizeIterator for Windows<'_> {
94 #[inline]
95 fn len(&self) -> usize {
96 match &self.inner {
97 WindowsInner::U8(v) => v.len(),
98 WindowsInner::U16(v) => v.len(),
99 }
100 }
101}
102
103#[derive(Debug, Clone)]
104enum CodePointsIterInner<'a> {
105 Latin1(std::iter::Copied<std::slice::Iter<'a, u8>>),
106 Utf16(std::char::DecodeUtf16<std::iter::Copied<std::slice::Iter<'a, u16>>>),
107}
108
109#[derive(Debug, Clone)]
110pub struct CodePointsIter<'a> {
111 inner: CodePointsIterInner<'a>,
112}
113
114impl<'a> CodePointsIter<'a> {
115 #[inline]
116 pub(crate) fn new(s: JsStr<'a>) -> Self {
117 let inner = match s.variant() {
118 JsStrVariant::Latin1(s) => CodePointsIterInner::Latin1(s.iter().copied()),
119 JsStrVariant::Utf16(s) => {
120 CodePointsIterInner::Utf16(char::decode_utf16(s.iter().copied()))
121 }
122 };
123 CodePointsIter { inner }
124 }
125}
126
127impl Iterator for CodePointsIter<'_> {
128 type Item = CodePoint;
129
130 #[inline]
131 fn next(&mut self) -> Option<Self::Item> {
132 match &mut self.inner {
133 CodePointsIterInner::Latin1(iter) => {
134 iter.next().map(|b| CodePoint::Unicode(char::from(b)))
135 }
136 CodePointsIterInner::Utf16(iter) => iter.next().map(|res| match res {
137 Ok(c) => CodePoint::Unicode(c),
138 Err(e) => CodePoint::UnpairedSurrogate(e.unpaired_surrogate()),
139 }),
140 }
141 }
142}
143
144impl FusedIterator for CodePointsIter<'_> {}