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