/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 | | } |