1use crate::error::FromRecoverableError;
2use crate::error::Needed;
3use crate::stream::AsBStr;
4use crate::stream::AsBytes;
5use crate::stream::Checkpoint;
6use crate::stream::Compare;
7use crate::stream::CompareResult;
8use crate::stream::FindSlice;
9use crate::stream::Location;
10use crate::stream::Offset;
11#[cfg(feature = "unstable-recover")]
12#[cfg(feature = "std")]
13use crate::stream::Recover;
14use crate::stream::SliceLen;
15use crate::stream::Stream;
16use crate::stream::StreamIsPartial;
17use crate::stream::UpdateSlice;
18
19#[derive(Clone, Debug)]
24pub struct Recoverable<I, E>
25where
26 I: Stream,
27{
28 input: I,
29 errors: Vec<E>,
30 is_recoverable: bool,
31}
32
33impl<I, E> Default for Recoverable<I, E>
34where
35 I: Default + Stream,
36{
37 #[inline]
38 fn default() -> Self {
39 Self::new(I::default())
40 }
41}
42
43impl<I, E> Recoverable<I, E>
44where
45 I: Stream,
46{
47 #[inline]
49 pub fn new(input: I) -> Self {
50 Self {
51 input,
52 errors: Default::default(),
53 is_recoverable: true,
54 }
55 }
56
57 #[inline]
59 pub fn unrecoverable(input: I) -> Self {
60 Self {
61 input,
62 errors: Default::default(),
63 is_recoverable: false,
64 }
65 }
66
67 #[inline]
69 pub fn into_parts(self) -> (I, Vec<E>) {
70 (self.input, self.errors)
71 }
72}
73
74impl<I, E> AsRef<I> for Recoverable<I, E>
75where
76 I: Stream,
77{
78 #[inline(always)]
79 fn as_ref(&self) -> &I {
80 &self.input
81 }
82}
83
84impl<I, E> crate::lib::std::ops::Deref for Recoverable<I, E>
85where
86 I: Stream,
87{
88 type Target = I;
89
90 #[inline(always)]
91 fn deref(&self) -> &Self::Target {
92 &self.input
93 }
94}
95
96impl<I: crate::lib::std::fmt::Display, E> crate::lib::std::fmt::Display for Recoverable<I, E>
97where
98 I: Stream,
99{
100 fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
101 crate::lib::std::fmt::Display::fmt(&self.input, f)
102 }
103}
104
105impl<I, E> SliceLen for Recoverable<I, E>
106where
107 I: SliceLen,
108 I: Stream,
109{
110 #[inline(always)]
111 fn slice_len(&self) -> usize {
112 self.input.slice_len()
113 }
114}
115
116impl<I, E: crate::lib::std::fmt::Debug> Stream for Recoverable<I, E>
117where
118 I: Stream,
119{
120 type Token = <I as Stream>::Token;
121 type Slice = <I as Stream>::Slice;
122
123 type IterOffsets = <I as Stream>::IterOffsets;
124
125 type Checkpoint = Checkpoint<I::Checkpoint, Self>;
126
127 #[inline(always)]
128 fn iter_offsets(&self) -> Self::IterOffsets {
129 self.input.iter_offsets()
130 }
131 #[inline(always)]
132 fn eof_offset(&self) -> usize {
133 self.input.eof_offset()
134 }
135
136 #[inline(always)]
137 fn next_token(&mut self) -> Option<Self::Token> {
138 self.input.next_token()
139 }
140
141 #[inline(always)]
142 fn peek_token(&self) -> Option<Self::Token> {
143 self.input.peek_token()
144 }
145
146 #[inline(always)]
147 fn offset_for<P>(&self, predicate: P) -> Option<usize>
148 where
149 P: Fn(Self::Token) -> bool,
150 {
151 self.input.offset_for(predicate)
152 }
153 #[inline(always)]
154 fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
155 self.input.offset_at(tokens)
156 }
157 #[inline(always)]
158 fn next_slice(&mut self, offset: usize) -> Self::Slice {
159 self.input.next_slice(offset)
160 }
161 #[inline(always)]
162 unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
163 unsafe { self.input.next_slice_unchecked(offset) }
165 }
166 #[inline(always)]
167 fn peek_slice(&self, offset: usize) -> Self::Slice {
168 self.input.peek_slice(offset)
169 }
170 #[inline(always)]
171 unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
172 unsafe { self.input.peek_slice_unchecked(offset) }
174 }
175
176 #[inline(always)]
177 fn checkpoint(&self) -> Self::Checkpoint {
178 Checkpoint::<_, Self>::new(self.input.checkpoint())
179 }
180 #[inline(always)]
181 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
182 self.input.reset(&checkpoint.inner);
183 }
184
185 #[inline(always)]
186 fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
187 &self.input
188 }
189}
190
191impl<I, E> Location for Recoverable<I, E>
192where
193 I: Location,
194 I: Stream,
195{
196 #[inline(always)]
197 fn previous_token_end(&self) -> usize {
198 self.input.previous_token_end()
199 }
200 #[inline(always)]
201 fn current_token_start(&self) -> usize {
202 self.input.current_token_start()
203 }
204}
205
206impl<I, E, R> Recover<E> for Recoverable<I, R>
207where
208 I: Stream,
209 R: FromRecoverableError<Self, E>,
210 R: crate::lib::std::fmt::Debug,
211 E: crate::error::ParserError<Self>,
212{
213 fn record_err(
214 &mut self,
215 token_start: &Self::Checkpoint,
216 err_start: &Self::Checkpoint,
217 err: E,
218 ) -> Result<(), E> {
219 if self.is_recoverable {
220 if err.is_incomplete() {
221 Err(err)
222 } else {
223 self.errors
224 .push(R::from_recoverable_error(token_start, err_start, self, err));
225 Ok(())
226 }
227 } else {
228 Err(err)
229 }
230 }
231
232 #[inline(always)]
234 fn is_recovery_supported() -> bool {
235 true
236 }
237}
238
239impl<I, E> StreamIsPartial for Recoverable<I, E>
240where
241 I: StreamIsPartial,
242 I: Stream,
243{
244 type PartialState = I::PartialState;
245
246 #[inline]
247 fn complete(&mut self) -> Self::PartialState {
248 self.input.complete()
249 }
250
251 #[inline]
252 fn restore_partial(&mut self, state: Self::PartialState) {
253 self.input.restore_partial(state);
254 }
255
256 #[inline(always)]
257 fn is_partial_supported() -> bool {
258 I::is_partial_supported()
259 }
260
261 #[inline(always)]
262 fn is_partial(&self) -> bool {
263 self.input.is_partial()
264 }
265}
266
267impl<I, E> Offset for Recoverable<I, E>
268where
269 I: Stream,
270 E: crate::lib::std::fmt::Debug,
271{
272 #[inline(always)]
273 fn offset_from(&self, other: &Self) -> usize {
274 self.offset_from(&other.checkpoint())
275 }
276}
277
278impl<I, E> Offset<<Recoverable<I, E> as Stream>::Checkpoint> for Recoverable<I, E>
279where
280 I: Stream,
281 E: crate::lib::std::fmt::Debug,
282{
283 #[inline(always)]
284 fn offset_from(&self, other: &<Recoverable<I, E> as Stream>::Checkpoint) -> usize {
285 self.checkpoint().offset_from(other)
286 }
287}
288
289impl<I, E> AsBytes for Recoverable<I, E>
290where
291 I: Stream,
292 I: AsBytes,
293{
294 #[inline(always)]
295 fn as_bytes(&self) -> &[u8] {
296 self.input.as_bytes()
297 }
298}
299
300impl<I, E> AsBStr for Recoverable<I, E>
301where
302 I: Stream,
303 I: AsBStr,
304{
305 #[inline(always)]
306 fn as_bstr(&self) -> &[u8] {
307 self.input.as_bstr()
308 }
309}
310
311impl<I, E, U> Compare<U> for Recoverable<I, E>
312where
313 I: Stream,
314 I: Compare<U>,
315{
316 #[inline(always)]
317 fn compare(&self, other: U) -> CompareResult {
318 self.input.compare(other)
319 }
320}
321
322impl<I, E, T> FindSlice<T> for Recoverable<I, E>
323where
324 I: Stream,
325 I: FindSlice<T>,
326{
327 #[inline(always)]
328 fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> {
329 self.input.find_slice(substr)
330 }
331}
332
333impl<I, E> UpdateSlice for Recoverable<I, E>
334where
335 I: Stream,
336 I: UpdateSlice,
337 E: crate::lib::std::fmt::Debug,
338{
339 #[inline(always)]
340 fn update_slice(mut self, inner: Self::Slice) -> Self {
341 self.input = I::update_slice(self.input, inner);
342 self
343 }
344}