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 | fn as_ref(&self) -> &I { |
68 | &self.input |
69 | } |
70 | } |
71 | |
72 | impl<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 | |
81 | impl<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 | |
87 | impl<I, S> SliceLen for Stateful<I, S> |
88 | where |
89 | I: SliceLen, |
90 | { |
91 | #[inline (always)] |
92 | fn slice_len(&self) -> usize { |
93 | self.input.slice_len() |
94 | } |
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 | 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 | &self.input |
166 | } |
167 | } |
168 | |
169 | impl<I, S> Location for Stateful<I, S> |
170 | where |
171 | I: Location, |
172 | { |
173 | #[inline (always)] |
174 | fn previous_token_end(&self) -> usize { |
175 | self.input.previous_token_end() |
176 | } |
177 | #[inline (always)] |
178 | fn current_token_start(&self) -> usize { |
179 | self.input.current_token_start() |
180 | } |
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 | fn complete(&mut self) -> Self::PartialState { |
216 | self.input.complete() |
217 | } |
218 | |
219 | #[inline ] |
220 | fn restore_partial(&mut self, state: Self::PartialState) { |
221 | self.input.restore_partial(state); |
222 | } |
223 | |
224 | #[inline (always)] |
225 | fn is_partial_supported() -> bool { |
226 | I::is_partial_supported() |
227 | } |
228 | |
229 | #[inline (always)] |
230 | fn is_partial(&self) -> bool { |
231 | self.input.is_partial() |
232 | } |
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 | fn offset_from(&self, start: &Self) -> usize { |
242 | self.offset_from(&start.checkpoint()) |
243 | } |
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 | fn offset_from(&self, other: &<Stateful<I, S> as Stream>::Checkpoint) -> usize { |
253 | self.checkpoint().offset_from(start:other) |
254 | } |
255 | } |
256 | |
257 | impl<I, S> AsBytes for Stateful<I, S> |
258 | where |
259 | I: AsBytes, |
260 | { |
261 | #[inline (always)] |
262 | fn as_bytes(&self) -> &[u8] { |
263 | self.input.as_bytes() |
264 | } |
265 | } |
266 | |
267 | impl<I, S> AsBStr for Stateful<I, S> |
268 | where |
269 | I: AsBStr, |
270 | { |
271 | #[inline (always)] |
272 | fn as_bstr(&self) -> &[u8] { |
273 | self.input.as_bstr() |
274 | } |
275 | } |
276 | |
277 | impl<I, S, U> Compare<U> for Stateful<I, S> |
278 | where |
279 | I: Compare<U>, |
280 | { |
281 | #[inline (always)] |
282 | fn compare(&self, other: U) -> CompareResult { |
283 | self.input.compare(other) |
284 | } |
285 | } |
286 | |
287 | impl<I, S, T> FindSlice<T> for Stateful<I, S> |
288 | where |
289 | I: FindSlice<T>, |
290 | { |
291 | #[inline (always)] |
292 | fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> { |
293 | self.input.find_slice(substr) |
294 | } |
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 | fn update_slice(mut self, inner: Self::Slice) -> Self { |
304 | self.input = I::update_slice(self.input, inner); |
305 | self |
306 | } |
307 | } |
308 | |