Skip to main content

winnow/stream/
stateful.rs

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