Skip to main content

ct_regex_internal/haystack/ext/
hipstr.rs

1use std::fmt::{self, Debug};
2use std::hash::{Hash, Hasher};
3use std::ops::Range;
4
5use hipstr::Backend;
6use hipstr::bytes::HipByt;
7use hipstr::string::HipStr;
8
9use crate::haystack::{
10    Haystack, HaystackSlice, IntoHaystack, OwnedHaystackable, first_char, first_char_and_width
11};
12
13impl<'a, B: Backend> HaystackSlice<'a> for HipStr<'a, B> {
14    type Item = char;
15
16    fn slice_with(&self, range: Range<usize>) -> Self {
17        self.slice(range)
18    }
19
20    fn as_bytes(&self) -> &[u8] {
21        HipStr::as_str(self).as_bytes()
22    }
23}
24
25/// A haystack type for matching against the [`char`]s in a [`HipStr<'a, B>`](hipstr::HipStr).
26pub struct HipStrStack<'a, B: Backend> {
27    inner: HipStr<'a, B>,
28    index: usize,
29}
30
31impl<'a, B: Backend> IntoHaystack<'a, HipStrStack<'a, B>> for HipStr<'a, B> {
32    fn into_haystack(self) -> HipStrStack<'a, B> {
33        HipStrStack {
34            inner: self,
35            index: 0,
36        }
37    }
38}
39
40impl<'a, B: Backend> Iterator for HipStrStack<'a, B> {
41    type Item = char;
42
43    fn next(&mut self) -> Option<Self::Item> {
44        let (width, first) = first_char_and_width(&self.remainder_as_slice());
45        // The width won't exceed the remaining slice, so it can't overflow then length.
46        self.index += width;
47        first
48    }
49}
50
51impl<'a, B: Backend> Haystack<'a> for HipStrStack<'a, B> {
52    type Slice = HipStr<'a, B>;
53
54    fn item(&self) -> Option<Self::Item> {
55        first_char(&self.remainder_as_slice())
56    }
57
58    fn prev_item(&self) -> Option<Self::Item> {
59        let prev_index = self.inner.floor_char_boundary(self.index.checked_sub(1)?);
60        first_char(&self.inner[prev_index..])
61    }
62
63    fn index(&self) -> usize {
64        self.index
65    }
66
67    fn inner_slice(&self) -> Self::Slice {
68        self.inner.clone()
69    }
70
71    fn remainder_as_slice(&self) -> Self::Slice {
72        self.inner.slice(self.index..)
73    }
74
75    fn go_to(&mut self, index: usize) {
76        self.index = index;
77    }
78}
79
80impl<'s, B: Backend> OwnedHaystackable<char> for HipStr<'s, B> {
81    type Hay<'a> = HipStrStack<'a, B> where Self: 'a;
82
83    fn replace_range<'a>(
84        &mut self,
85        range: Range<usize>,
86        with: <Self::Hay<'a> as Haystack<'a>>::Slice
87    ) where Self: 'a {
88        self.mutate().replace_range(range, &with);
89    }
90
91    fn as_haystack<'a>(&'a self) -> Self::Hay<'a> {
92        self.clone().into_haystack()
93    }
94
95    fn as_slice<'a>(&'a self) -> <Self::Hay<'a> as Haystack<'a>>::Slice {
96        self.clone()
97    }
98
99    fn len(&self) -> usize {
100        self.len()
101    }
102}
103
104// Implemented to relax B: Debug bound.
105impl<'a, B: Backend> Debug for HipStrStack<'a, B> {
106    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107        f.debug_struct("HipStrStack")
108            .field("inner", &self.inner)
109            .field("index", &self.index)
110            .finish()
111    }
112}
113
114impl<'a, B: Backend> Clone for HipStrStack<'a, B> {
115    fn clone(&self) -> Self {
116        Self {
117            inner: self.inner.clone(),
118            index: self.index,
119        }
120    }
121}
122
123impl<'a, B: Backend + Hash> Hash for HipStrStack<'a, B> {
124    fn hash<H: Hasher>(&self, state: &mut H) {
125        self.inner.hash(state);
126        self.index.hash(state);
127    }
128}
129
130impl<'a, B: Backend> HaystackSlice<'a> for HipByt<'a, B> {
131    type Item = u8;
132
133    fn slice_with(&self, range: Range<usize>) -> Self {
134        self.slice(range)
135    }
136
137    fn as_bytes(&self) -> &[u8] {
138        HipByt::as_slice(self)
139    }
140}
141
142/// A haystack type for matching against the [`u8`]s in a [`HipByt<'a, B>`](hipstr::HipByt).
143pub struct HipBytStack<'a, B: Backend> {
144    inner: HipByt<'a, B>,
145    index: usize,
146}
147
148impl<'a, B: Backend> IntoHaystack<'a, HipBytStack<'a, B>> for HipByt<'a, B> {
149    fn into_haystack(self) -> HipBytStack<'a, B> {
150        HipBytStack {
151            inner: self,
152            index: 0,
153        }
154    }
155}
156
157impl<'a, B: Backend> Iterator for HipBytStack<'a, B> {
158    type Item = u8;
159
160    fn next(&mut self) -> Option<Self::Item> {
161        let byte = self.inner.get(self.index).copied();
162
163        if byte.is_some() {
164            self.index += 1;
165        }
166
167        byte
168    }
169}
170
171impl<'a, B: Backend> Haystack<'a> for HipBytStack<'a, B> {
172    type Slice = HipByt<'a, B>;
173
174    fn item(&self) -> Option<Self::Item> {
175        self.inner.get(self.index).copied()
176    }
177
178    fn prev_item(&self) -> Option<Self::Item> {
179        self.inner.get(self.index.checked_sub(1)?).copied()
180    }
181
182    fn index(&self) -> usize {
183        self.index
184    }
185
186    fn inner_slice(&self) -> Self::Slice {
187        self.inner.clone()
188    }
189
190    fn remainder_as_slice(&self) -> Self::Slice {
191        self.inner.slice(self.index..)
192    }
193
194    fn go_to(&mut self, index: usize) {
195        self.index = index;
196    }
197}
198
199impl<'a, B: Backend> Debug for HipBytStack<'a, B> {
200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201        f.debug_struct("HipBytStack")
202            .field("inner", &self.inner)
203            .field("index", &self.index)
204            .finish()
205    }
206}
207
208impl<'a, B: Backend> Clone for HipBytStack<'a, B> {
209    fn clone(&self) -> Self {
210        Self {
211            inner: self.inner.clone(),
212            index: self.index,
213        }
214    }
215}
216
217impl<'a, B: Backend + Hash> Hash for HipBytStack<'a, B> {
218    fn hash<H: Hasher>(&self, state: &mut H) {
219        self.inner.hash(state);
220        self.index.hash(state);
221    }
222}
223
224impl<'s, B: Backend> OwnedHaystackable<u8> for HipByt<'s, B> {
225    type Hay<'a> = HipBytStack<'a, B> where Self: 'a;
226
227    fn replace_range<'a>(
228        &mut self,
229        range: Range<usize>,
230        with: <Self::Hay<'a> as Haystack<'a>>::Slice
231    ) where Self: 'a {
232        self.mutate().splice(range, with.iter().copied());
233    }
234
235    fn as_haystack<'a>(&'a self) -> Self::Hay<'a> {
236        self.clone().into_haystack()
237    }
238
239    fn as_slice<'a>(&'a self) -> <Self::Hay<'a> as Haystack<'a>>::Slice {
240        self.clone()
241    }
242
243    fn len(&self) -> usize {
244        self.len()
245    }
246}