winnow/stream/
locating.rs
1use crate::error::Needed;
2use crate::stream::AsBStr;
3use crate::stream::AsBytes;
4use crate::stream::Checkpoint;
5use crate::stream::Compare;
6use crate::stream::CompareResult;
7use crate::stream::FindSlice;
8use crate::stream::Location;
9use crate::stream::Offset;
10#[cfg(feature = "unstable-recover")]
11#[cfg(feature = "std")]
12use crate::stream::Recover;
13use crate::stream::SliceLen;
14use crate::stream::Stream;
15use crate::stream::StreamIsPartial;
16use crate::stream::UpdateSlice;
17
18#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
29#[doc(alias = "LocatingSliceSpan")]
30#[doc(alias = "Located")]
31pub struct LocatingSlice<I> {
32 initial: I,
33 input: I,
34}
35
36impl<I> LocatingSlice<I>
37where
38 I: Clone + Offset,
39{
40 pub fn new(input: I) -> Self {
42 let initial = input.clone();
43 Self { initial, input }
44 }
45
46 #[inline]
47 fn previous_token_end(&self) -> usize {
48 self.input.offset_from(&self.initial)
52 }
53 #[inline]
54 fn current_token_start(&self) -> usize {
55 self.input.offset_from(&self.initial)
58 }
59}
60
61impl<I> LocatingSlice<I>
62where
63 I: Clone + Stream + Offset,
64{
65 #[doc(alias = "fseek")]
70 #[inline]
71 pub fn reset_to_start(&mut self) {
72 let start = self.initial.checkpoint();
73 self.input.reset(&start);
74 }
75}
76
77impl<I> AsRef<I> for LocatingSlice<I> {
78 #[inline(always)]
79 fn as_ref(&self) -> &I {
80 &self.input
81 }
82}
83
84impl<I> crate::lib::std::ops::Deref for LocatingSlice<I> {
85 type Target = I;
86
87 #[inline(always)]
88 fn deref(&self) -> &Self::Target {
89 &self.input
90 }
91}
92
93impl<I: crate::lib::std::fmt::Display> crate::lib::std::fmt::Display for LocatingSlice<I> {
94 fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
95 self.input.fmt(f)
96 }
97}
98
99impl<I> SliceLen for LocatingSlice<I>
100where
101 I: SliceLen,
102{
103 #[inline(always)]
104 fn slice_len(&self) -> usize {
105 self.input.slice_len()
106 }
107}
108
109impl<I: Stream> Stream for LocatingSlice<I> {
110 type Token = <I as Stream>::Token;
111 type Slice = <I as Stream>::Slice;
112
113 type IterOffsets = <I as Stream>::IterOffsets;
114
115 type Checkpoint = Checkpoint<I::Checkpoint, Self>;
116
117 #[inline(always)]
118 fn iter_offsets(&self) -> Self::IterOffsets {
119 self.input.iter_offsets()
120 }
121 #[inline(always)]
122 fn eof_offset(&self) -> usize {
123 self.input.eof_offset()
124 }
125
126 #[inline(always)]
127 fn next_token(&mut self) -> Option<Self::Token> {
128 self.input.next_token()
129 }
130
131 #[inline(always)]
132 fn peek_token(&self) -> Option<Self::Token> {
133 self.input.peek_token()
134 }
135
136 #[inline(always)]
137 fn offset_for<P>(&self, predicate: P) -> Option<usize>
138 where
139 P: Fn(Self::Token) -> bool,
140 {
141 self.input.offset_for(predicate)
142 }
143 #[inline(always)]
144 fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
145 self.input.offset_at(tokens)
146 }
147 #[inline(always)]
148 fn next_slice(&mut self, offset: usize) -> Self::Slice {
149 self.input.next_slice(offset)
150 }
151 #[inline(always)]
152 unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
153 unsafe { self.input.next_slice_unchecked(offset) }
155 }
156 #[inline(always)]
157 fn peek_slice(&self, offset: usize) -> Self::Slice {
158 self.input.peek_slice(offset)
159 }
160 #[inline(always)]
161 unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
162 unsafe { self.input.peek_slice_unchecked(offset) }
164 }
165
166 #[inline(always)]
167 fn checkpoint(&self) -> Self::Checkpoint {
168 Checkpoint::<_, Self>::new(self.input.checkpoint())
169 }
170 #[inline(always)]
171 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
172 self.input.reset(&checkpoint.inner);
173 }
174
175 #[inline(always)]
176 fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
177 &self.input
178 }
179}
180
181impl<I> Location for LocatingSlice<I>
182where
183 I: Clone + Offset,
184{
185 #[inline(always)]
186 fn previous_token_end(&self) -> usize {
187 self.previous_token_end()
188 }
189 #[inline(always)]
190 fn current_token_start(&self) -> usize {
191 self.current_token_start()
192 }
193}
194
195#[cfg(feature = "unstable-recover")]
196#[cfg(feature = "std")]
197impl<I, E> Recover<E> for LocatingSlice<I>
198where
199 I: Recover<E>,
200 I: Stream,
201{
202 #[inline(always)]
203 fn record_err(
204 &mut self,
205 _token_start: &Self::Checkpoint,
206 _err_start: &Self::Checkpoint,
207 err: E,
208 ) -> Result<(), E> {
209 Err(err)
210 }
211
212 #[inline(always)]
214 fn is_recovery_supported() -> bool {
215 false
216 }
217}
218
219impl<I> StreamIsPartial for LocatingSlice<I>
220where
221 I: StreamIsPartial,
222{
223 type PartialState = I::PartialState;
224
225 #[inline]
226 fn complete(&mut self) -> Self::PartialState {
227 self.input.complete()
228 }
229
230 #[inline]
231 fn restore_partial(&mut self, state: Self::PartialState) {
232 self.input.restore_partial(state);
233 }
234
235 #[inline(always)]
236 fn is_partial_supported() -> bool {
237 I::is_partial_supported()
238 }
239
240 #[inline(always)]
241 fn is_partial(&self) -> bool {
242 self.input.is_partial()
243 }
244}
245
246impl<I> Offset for LocatingSlice<I>
247where
248 I: Stream,
249{
250 #[inline(always)]
251 fn offset_from(&self, other: &Self) -> usize {
252 self.offset_from(&other.checkpoint())
253 }
254}
255
256impl<I> Offset<<LocatingSlice<I> as Stream>::Checkpoint> for LocatingSlice<I>
257where
258 I: Stream,
259{
260 #[inline(always)]
261 fn offset_from(&self, other: &<LocatingSlice<I> as Stream>::Checkpoint) -> usize {
262 self.checkpoint().offset_from(other)
263 }
264}
265
266impl<I> AsBytes for LocatingSlice<I>
267where
268 I: AsBytes,
269{
270 #[inline(always)]
271 fn as_bytes(&self) -> &[u8] {
272 self.input.as_bytes()
273 }
274}
275
276impl<I> AsBStr for LocatingSlice<I>
277where
278 I: AsBStr,
279{
280 #[inline(always)]
281 fn as_bstr(&self) -> &[u8] {
282 self.input.as_bstr()
283 }
284}
285
286impl<I, U> Compare<U> for LocatingSlice<I>
287where
288 I: Compare<U>,
289{
290 #[inline(always)]
291 fn compare(&self, other: U) -> CompareResult {
292 self.input.compare(other)
293 }
294}
295
296impl<I, T> FindSlice<T> for LocatingSlice<I>
297where
298 I: FindSlice<T>,
299{
300 #[inline(always)]
301 fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> {
302 self.input.find_slice(substr)
303 }
304}
305
306impl<I> UpdateSlice for LocatingSlice<I>
307where
308 I: UpdateSlice,
309{
310 #[inline(always)]
311 fn update_slice(mut self, inner: Self::Slice) -> Self {
312 self.input = I::update_slice(self.input, inner);
313 self
314 }
315}