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, 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: core::fmt::Debug> core::fmt::Debug for LocatingSlice<I> {
85 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
86 self.input.fmt(f)
87 }
88}
89
90impl<I> crate::lib::std::ops::Deref for LocatingSlice<I> {
91 type Target = I;
92
93 #[inline(always)]
94 fn deref(&self) -> &Self::Target {
95 &self.input
96 }
97}
98
99impl<I: crate::lib::std::fmt::Display> crate::lib::std::fmt::Display for LocatingSlice<I> {
100 fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
101 self.input.fmt(f)
102 }
103}
104
105impl<I> SliceLen for LocatingSlice<I>
106where
107 I: SliceLen,
108{
109 #[inline(always)]
110 fn slice_len(&self) -> usize {
111 self.input.slice_len()
112 }
113}
114
115impl<I: Stream> Stream for LocatingSlice<I> {
116 type Token = <I as Stream>::Token;
117 type Slice = <I as Stream>::Slice;
118
119 type IterOffsets = <I as Stream>::IterOffsets;
120
121 type Checkpoint = Checkpoint<I::Checkpoint, Self>;
122
123 #[inline(always)]
124 fn iter_offsets(&self) -> Self::IterOffsets {
125 self.input.iter_offsets()
126 }
127 #[inline(always)]
128 fn eof_offset(&self) -> usize {
129 self.input.eof_offset()
130 }
131
132 #[inline(always)]
133 fn next_token(&mut self) -> Option<Self::Token> {
134 self.input.next_token()
135 }
136
137 #[inline(always)]
138 fn peek_token(&self) -> Option<Self::Token> {
139 self.input.peek_token()
140 }
141
142 #[inline(always)]
143 fn offset_for<P>(&self, predicate: P) -> Option<usize>
144 where
145 P: Fn(Self::Token) -> bool,
146 {
147 self.input.offset_for(predicate)
148 }
149 #[inline(always)]
150 fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
151 self.input.offset_at(tokens)
152 }
153 #[inline(always)]
154 fn next_slice(&mut self, offset: usize) -> Self::Slice {
155 self.input.next_slice(offset)
156 }
157 #[inline(always)]
158 unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
159 unsafe { self.input.next_slice_unchecked(offset) }
161 }
162 #[inline(always)]
163 fn peek_slice(&self, offset: usize) -> Self::Slice {
164 self.input.peek_slice(offset)
165 }
166 #[inline(always)]
167 unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
168 unsafe { self.input.peek_slice_unchecked(offset) }
170 }
171
172 #[inline(always)]
173 fn checkpoint(&self) -> Self::Checkpoint {
174 Checkpoint::<_, Self>::new(self.input.checkpoint())
175 }
176 #[inline(always)]
177 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
178 self.input.reset(&checkpoint.inner);
179 }
180
181 #[inline(always)]
182 fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
183 #![allow(deprecated)]
184 self.input.raw()
185 }
186
187 fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
188 self.input.trace(f)
189 }
190}
191
192impl<I> Location for LocatingSlice<I>
193where
194 I: Clone + Offset,
195{
196 #[inline(always)]
197 fn previous_token_end(&self) -> usize {
198 self.previous_token_end()
199 }
200 #[inline(always)]
201 fn current_token_start(&self) -> usize {
202 self.current_token_start()
203 }
204}
205
206#[cfg(feature = "unstable-recover")]
207#[cfg(feature = "std")]
208impl<I, E> Recover<E> for LocatingSlice<I>
209where
210 I: Recover<E>,
211 I: Stream,
212{
213 #[inline(always)]
214 fn record_err(
215 &mut self,
216 _token_start: &Self::Checkpoint,
217 _err_start: &Self::Checkpoint,
218 err: E,
219 ) -> Result<(), E> {
220 Err(err)
221 }
222
223 #[inline(always)]
225 fn is_recovery_supported() -> bool {
226 false
227 }
228}
229
230impl<I> StreamIsPartial for LocatingSlice<I>
231where
232 I: StreamIsPartial,
233{
234 type PartialState = I::PartialState;
235
236 #[inline]
237 fn complete(&mut self) -> Self::PartialState {
238 self.input.complete()
239 }
240
241 #[inline]
242 fn restore_partial(&mut self, state: Self::PartialState) {
243 self.input.restore_partial(state);
244 }
245
246 #[inline(always)]
247 fn is_partial_supported() -> bool {
248 I::is_partial_supported()
249 }
250
251 #[inline(always)]
252 fn is_partial(&self) -> bool {
253 self.input.is_partial()
254 }
255}
256
257impl<I> Offset for LocatingSlice<I>
258where
259 I: Stream,
260{
261 #[inline(always)]
262 fn offset_from(&self, other: &Self) -> usize {
263 self.offset_from(&other.checkpoint())
264 }
265}
266
267impl<I> Offset<<LocatingSlice<I> as Stream>::Checkpoint> for LocatingSlice<I>
268where
269 I: Stream,
270{
271 #[inline(always)]
272 fn offset_from(&self, other: &<LocatingSlice<I> as Stream>::Checkpoint) -> usize {
273 self.checkpoint().offset_from(other)
274 }
275}
276
277impl<I> AsBytes for LocatingSlice<I>
278where
279 I: AsBytes,
280{
281 #[inline(always)]
282 fn as_bytes(&self) -> &[u8] {
283 self.input.as_bytes()
284 }
285}
286
287impl<I> AsBStr for LocatingSlice<I>
288where
289 I: AsBStr,
290{
291 #[inline(always)]
292 fn as_bstr(&self) -> &[u8] {
293 self.input.as_bstr()
294 }
295}
296
297impl<I, U> Compare<U> for LocatingSlice<I>
298where
299 I: Compare<U>,
300{
301 #[inline(always)]
302 fn compare(&self, other: U) -> CompareResult {
303 self.input.compare(other)
304 }
305}
306
307impl<I, T> FindSlice<T> for LocatingSlice<I>
308where
309 I: FindSlice<T>,
310{
311 #[inline(always)]
312 fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> {
313 self.input.find_slice(substr)
314 }
315}
316
317impl<I> UpdateSlice for LocatingSlice<I>
318where
319 I: UpdateSlice,
320{
321 #[inline(always)]
322 fn update_slice(mut self, inner: Self::Slice) -> Self {
323 self.input = I::update_slice(self.input, inner);
324 self
325 }
326}