winnow/stream/
stateful.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/// Thread global state through your parsers
19///
20/// Use cases
21/// - Recursion checks
22/// - Error recovery
23/// - Debugging
24///
25/// # Example
26///
27/// ```
28/// # use std::cell::Cell;
29/// # use winnow::prelude::*;
30/// # use winnow::stream::Stateful;
31/// # use winnow::ascii::alpha1;
32/// # type Error = ();
33///
34/// #[derive(Debug)]
35/// struct State<'s>(&'s mut u32);
36///
37/// impl<'s> State<'s> {
38///     fn count(&mut self) {
39///         *self.0 += 1;
40///     }
41/// }
42///
43/// type Stream<'is> = Stateful<&'is str, State<'is>>;
44///
45/// fn word<'s>(i: &mut Stream<'s>) -> ModalResult<&'s str> {
46///   i.state.count();
47///   alpha1.parse_next(i)
48/// }
49///
50/// let data = "Hello";
51/// let mut state = 0;
52/// let input = Stream { input: data, state: State(&mut state) };
53/// let output = word.parse(input).unwrap();
54/// assert_eq!(state, 1);
55/// ```
56#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
57#[doc(alias = "LocatingSliceSpan")]
58pub struct Stateful<I, S> {
59    /// Inner input being wrapped in state
60    pub input: I,
61    /// User-provided state
62    pub state: S,
63}
64
65impl<I, S> AsRef<I> for Stateful<I, S> {
66    #[inline(always)]
67    fn as_ref(&self) -> &I {
68        &self.input
69    }
70}
71
72impl<I, S> crate::lib::std::ops::Deref for Stateful<I, S> {
73    type Target = I;
74
75    #[inline(always)]
76    fn deref(&self) -> &Self::Target {
77        self.as_ref()
78    }
79}
80
81impl<I: crate::lib::std::fmt::Display, S> crate::lib::std::fmt::Display for Stateful<I, S> {
82    fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
83        self.input.fmt(f)
84    }
85}
86
87impl<I, S> SliceLen for Stateful<I, S>
88where
89    I: SliceLen,
90{
91    #[inline(always)]
92    fn slice_len(&self) -> usize {
93        self.input.slice_len()
94    }
95}
96
97impl<I: Stream, S: crate::lib::std::fmt::Debug> Stream for Stateful<I, S> {
98    type Token = <I as Stream>::Token;
99    type Slice = <I as Stream>::Slice;
100
101    type IterOffsets = <I as Stream>::IterOffsets;
102
103    type Checkpoint = Checkpoint<I::Checkpoint, Self>;
104
105    #[inline(always)]
106    fn iter_offsets(&self) -> Self::IterOffsets {
107        self.input.iter_offsets()
108    }
109    #[inline(always)]
110    fn eof_offset(&self) -> usize {
111        self.input.eof_offset()
112    }
113
114    #[inline(always)]
115    fn next_token(&mut self) -> Option<Self::Token> {
116        self.input.next_token()
117    }
118
119    #[inline(always)]
120    fn peek_token(&self) -> Option<Self::Token> {
121        self.input.peek_token()
122    }
123
124    #[inline(always)]
125    fn offset_for<P>(&self, predicate: P) -> Option<usize>
126    where
127        P: Fn(Self::Token) -> bool,
128    {
129        self.input.offset_for(predicate)
130    }
131    #[inline(always)]
132    fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
133        self.input.offset_at(tokens)
134    }
135    #[inline(always)]
136    fn next_slice(&mut self, offset: usize) -> Self::Slice {
137        self.input.next_slice(offset)
138    }
139    #[inline(always)]
140    unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
141        // SAFETY: Passing up invariants
142        unsafe { self.input.next_slice_unchecked(offset) }
143    }
144    #[inline(always)]
145    fn peek_slice(&self, offset: usize) -> Self::Slice {
146        self.input.peek_slice(offset)
147    }
148    #[inline(always)]
149    unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
150        // SAFETY: Passing up invariants
151        unsafe { self.input.peek_slice_unchecked(offset) }
152    }
153
154    #[inline(always)]
155    fn checkpoint(&self) -> Self::Checkpoint {
156        Checkpoint::<_, Self>::new(self.input.checkpoint())
157    }
158    #[inline(always)]
159    fn reset(&mut self, checkpoint: &Self::Checkpoint) {
160        self.input.reset(&checkpoint.inner);
161    }
162
163    #[inline(always)]
164    fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
165        #![allow(deprecated)]
166        self.input.raw()
167    }
168
169    fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
170        self.input.trace(f)
171    }
172}
173
174impl<I, S> Location for Stateful<I, S>
175where
176    I: Location,
177{
178    #[inline(always)]
179    fn previous_token_end(&self) -> usize {
180        self.input.previous_token_end()
181    }
182    #[inline(always)]
183    fn current_token_start(&self) -> usize {
184        self.input.current_token_start()
185    }
186}
187
188#[cfg(feature = "unstable-recover")]
189#[cfg(feature = "std")]
190impl<I, E, S> Recover<E> for Stateful<I, S>
191where
192    I: Recover<E>,
193    I: Stream,
194    S: Clone + crate::lib::std::fmt::Debug,
195{
196    #[inline(always)]
197    fn record_err(
198        &mut self,
199        _token_start: &Self::Checkpoint,
200        _err_start: &Self::Checkpoint,
201        err: E,
202    ) -> Result<(), E> {
203        Err(err)
204    }
205
206    /// Report whether the [`Stream`] can save off errors for recovery
207    #[inline(always)]
208    fn is_recovery_supported() -> bool {
209        false
210    }
211}
212
213impl<I, S> StreamIsPartial for Stateful<I, S>
214where
215    I: StreamIsPartial,
216{
217    type PartialState = I::PartialState;
218
219    #[inline]
220    fn complete(&mut self) -> Self::PartialState {
221        self.input.complete()
222    }
223
224    #[inline]
225    fn restore_partial(&mut self, state: Self::PartialState) {
226        self.input.restore_partial(state);
227    }
228
229    #[inline(always)]
230    fn is_partial_supported() -> bool {
231        I::is_partial_supported()
232    }
233
234    #[inline(always)]
235    fn is_partial(&self) -> bool {
236        self.input.is_partial()
237    }
238}
239
240impl<I, S> Offset for Stateful<I, S>
241where
242    I: Stream,
243    S: Clone + crate::lib::std::fmt::Debug,
244{
245    #[inline(always)]
246    fn offset_from(&self, start: &Self) -> usize {
247        self.offset_from(&start.checkpoint())
248    }
249}
250
251impl<I, S> Offset<<Stateful<I, S> as Stream>::Checkpoint> for Stateful<I, S>
252where
253    I: Stream,
254    S: crate::lib::std::fmt::Debug,
255{
256    #[inline(always)]
257    fn offset_from(&self, other: &<Stateful<I, S> as Stream>::Checkpoint) -> usize {
258        self.checkpoint().offset_from(other)
259    }
260}
261
262impl<I, S> AsBytes for Stateful<I, S>
263where
264    I: AsBytes,
265{
266    #[inline(always)]
267    fn as_bytes(&self) -> &[u8] {
268        self.input.as_bytes()
269    }
270}
271
272impl<I, S> AsBStr for Stateful<I, S>
273where
274    I: AsBStr,
275{
276    #[inline(always)]
277    fn as_bstr(&self) -> &[u8] {
278        self.input.as_bstr()
279    }
280}
281
282impl<I, S, U> Compare<U> for Stateful<I, S>
283where
284    I: Compare<U>,
285{
286    #[inline(always)]
287    fn compare(&self, other: U) -> CompareResult {
288        self.input.compare(other)
289    }
290}
291
292impl<I, S, T> FindSlice<T> for Stateful<I, S>
293where
294    I: FindSlice<T>,
295{
296    #[inline(always)]
297    fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> {
298        self.input.find_slice(substr)
299    }
300}
301
302impl<I, S> UpdateSlice for Stateful<I, S>
303where
304    I: UpdateSlice,
305    S: Clone + crate::lib::std::fmt::Debug,
306{
307    #[inline(always)]
308    fn update_slice(mut self, inner: Self::Slice) -> Self {
309        self.input = I::update_slice(self.input, inner);
310        self
311    }
312}