Coverage Report

Created: 2025-11-16 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/winnow-0.7.6/src/stream/stateful.rs
Line
Count
Source
1
use crate::error::Needed;
2
use crate::stream::AsBStr;
3
use crate::stream::AsBytes;
4
use crate::stream::Checkpoint;
5
use crate::stream::Compare;
6
use crate::stream::CompareResult;
7
use crate::stream::FindSlice;
8
use crate::stream::Location;
9
use crate::stream::Offset;
10
#[cfg(feature = "unstable-recover")]
11
#[cfg(feature = "std")]
12
use crate::stream::Recover;
13
use crate::stream::SliceLen;
14
use crate::stream::Stream;
15
use crate::stream::StreamIsPartial;
16
use 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")]
58
pub 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
65
impl<I, S> AsRef<I> for Stateful<I, S> {
66
    #[inline(always)]
67
0
    fn as_ref(&self) -> &I {
68
0
        &self.input
69
0
    }
70
}
71
72
impl<I, S> crate::lib::std::ops::Deref for Stateful<I, S> {
73
    type Target = I;
74
75
    #[inline(always)]
76
0
    fn deref(&self) -> &Self::Target {
77
0
        self.as_ref()
78
0
    }
79
}
80
81
impl<I: crate::lib::std::fmt::Display, S> crate::lib::std::fmt::Display for Stateful<I, S> {
82
0
    fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
83
0
        self.input.fmt(f)
84
0
    }
85
}
86
87
impl<I, S> SliceLen for Stateful<I, S>
88
where
89
    I: SliceLen,
90
{
91
    #[inline(always)]
92
0
    fn slice_len(&self) -> usize {
93
0
        self.input.slice_len()
94
0
    }
95
}
96
97
impl<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
0
    fn iter_offsets(&self) -> Self::IterOffsets {
107
0
        self.input.iter_offsets()
108
0
    }
109
    #[inline(always)]
110
0
    fn eof_offset(&self) -> usize {
111
0
        self.input.eof_offset()
112
0
    }
113
114
    #[inline(always)]
115
0
    fn next_token(&mut self) -> Option<Self::Token> {
116
0
        self.input.next_token()
117
0
    }
118
119
    #[inline(always)]
120
0
    fn peek_token(&self) -> Option<Self::Token> {
121
0
        self.input.peek_token()
122
0
    }
123
124
    #[inline(always)]
125
0
    fn offset_for<P>(&self, predicate: P) -> Option<usize>
126
0
    where
127
0
        P: Fn(Self::Token) -> bool,
128
    {
129
0
        self.input.offset_for(predicate)
130
0
    }
131
    #[inline(always)]
132
0
    fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
133
0
        self.input.offset_at(tokens)
134
0
    }
135
    #[inline(always)]
136
0
    fn next_slice(&mut self, offset: usize) -> Self::Slice {
137
0
        self.input.next_slice(offset)
138
0
    }
139
    #[inline(always)]
140
0
    unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
141
        // SAFETY: Passing up invariants
142
0
        unsafe { self.input.next_slice_unchecked(offset) }
143
0
    }
144
    #[inline(always)]
145
0
    fn peek_slice(&self, offset: usize) -> Self::Slice {
146
0
        self.input.peek_slice(offset)
147
0
    }
148
    #[inline(always)]
149
0
    unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
150
        // SAFETY: Passing up invariants
151
0
        unsafe { self.input.peek_slice_unchecked(offset) }
152
0
    }
153
154
    #[inline(always)]
155
0
    fn checkpoint(&self) -> Self::Checkpoint {
156
0
        Checkpoint::<_, Self>::new(self.input.checkpoint())
157
0
    }
158
    #[inline(always)]
159
0
    fn reset(&mut self, checkpoint: &Self::Checkpoint) {
160
0
        self.input.reset(&checkpoint.inner);
161
0
    }
162
163
    #[inline(always)]
164
0
    fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
165
0
        &self.input
166
0
    }
167
}
168
169
impl<I, S> Location for Stateful<I, S>
170
where
171
    I: Location,
172
{
173
    #[inline(always)]
174
0
    fn previous_token_end(&self) -> usize {
175
0
        self.input.previous_token_end()
176
0
    }
177
    #[inline(always)]
178
0
    fn current_token_start(&self) -> usize {
179
0
        self.input.current_token_start()
180
0
    }
181
}
182
183
#[cfg(feature = "unstable-recover")]
184
#[cfg(feature = "std")]
185
impl<I, E, S> Recover<E> for Stateful<I, S>
186
where
187
    I: Recover<E>,
188
    I: Stream,
189
    S: Clone + crate::lib::std::fmt::Debug,
190
{
191
    #[inline(always)]
192
    fn record_err(
193
        &mut self,
194
        _token_start: &Self::Checkpoint,
195
        _err_start: &Self::Checkpoint,
196
        err: E,
197
    ) -> Result<(), E> {
198
        Err(err)
199
    }
200
201
    /// Report whether the [`Stream`] can save off errors for recovery
202
    #[inline(always)]
203
    fn is_recovery_supported() -> bool {
204
        false
205
    }
206
}
207
208
impl<I, S> StreamIsPartial for Stateful<I, S>
209
where
210
    I: StreamIsPartial,
211
{
212
    type PartialState = I::PartialState;
213
214
    #[inline]
215
0
    fn complete(&mut self) -> Self::PartialState {
216
0
        self.input.complete()
217
0
    }
218
219
    #[inline]
220
0
    fn restore_partial(&mut self, state: Self::PartialState) {
221
0
        self.input.restore_partial(state);
222
0
    }
223
224
    #[inline(always)]
225
0
    fn is_partial_supported() -> bool {
226
0
        I::is_partial_supported()
227
0
    }
228
229
    #[inline(always)]
230
0
    fn is_partial(&self) -> bool {
231
0
        self.input.is_partial()
232
0
    }
233
}
234
235
impl<I, S> Offset for Stateful<I, S>
236
where
237
    I: Stream,
238
    S: Clone + crate::lib::std::fmt::Debug,
239
{
240
    #[inline(always)]
241
0
    fn offset_from(&self, start: &Self) -> usize {
242
0
        self.offset_from(&start.checkpoint())
243
0
    }
244
}
245
246
impl<I, S> Offset<<Stateful<I, S> as Stream>::Checkpoint> for Stateful<I, S>
247
where
248
    I: Stream,
249
    S: crate::lib::std::fmt::Debug,
250
{
251
    #[inline(always)]
252
0
    fn offset_from(&self, other: &<Stateful<I, S> as Stream>::Checkpoint) -> usize {
253
0
        self.checkpoint().offset_from(other)
254
0
    }
255
}
256
257
impl<I, S> AsBytes for Stateful<I, S>
258
where
259
    I: AsBytes,
260
{
261
    #[inline(always)]
262
0
    fn as_bytes(&self) -> &[u8] {
263
0
        self.input.as_bytes()
264
0
    }
265
}
266
267
impl<I, S> AsBStr for Stateful<I, S>
268
where
269
    I: AsBStr,
270
{
271
    #[inline(always)]
272
0
    fn as_bstr(&self) -> &[u8] {
273
0
        self.input.as_bstr()
274
0
    }
275
}
276
277
impl<I, S, U> Compare<U> for Stateful<I, S>
278
where
279
    I: Compare<U>,
280
{
281
    #[inline(always)]
282
0
    fn compare(&self, other: U) -> CompareResult {
283
0
        self.input.compare(other)
284
0
    }
285
}
286
287
impl<I, S, T> FindSlice<T> for Stateful<I, S>
288
where
289
    I: FindSlice<T>,
290
{
291
    #[inline(always)]
292
0
    fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> {
293
0
        self.input.find_slice(substr)
294
0
    }
295
}
296
297
impl<I, S> UpdateSlice for Stateful<I, S>
298
where
299
    I: UpdateSlice,
300
    S: Clone + crate::lib::std::fmt::Debug,
301
{
302
    #[inline(always)]
303
0
    fn update_slice(mut self, inner: Self::Slice) -> Self {
304
0
        self.input = I::update_slice(self.input, inner);
305
0
        self
306
0
    }
307
}