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 fn peek_slice(&self, offset: usize) -> Self::Slice {
163 self.input.peek_slice(offset)
164 }
165
166 #[inline(always)]
167 fn checkpoint(&self) -> Self::Checkpoint {
168 Checkpoint::<_, Self>::new(self.input.checkpoint())
169 }
170 #[inline(always)]
171 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
172 self.input.reset(&checkpoint.inner);
173 }
174
175 #[inline(always)]
176 fn raw(&self) -> &dyn crate::lib::std::fmt::Debug {
177 &self.input
178 }
179}
180
181impl<I, E> Location for Recoverable<I, E>
182where
183 I: Location,
184 I: Stream,
185{
186 #[inline(always)]
187 fn previous_token_end(&self) -> usize {
188 self.input.previous_token_end()
189 }
190 #[inline(always)]
191 fn current_token_start(&self) -> usize {
192 self.input.current_token_start()
193 }
194}
195
196impl<I, E, R> Recover<E> for Recoverable<I, R>
197where
198 I: Stream,
199 R: FromRecoverableError<Self, E>,
200 R: crate::lib::std::fmt::Debug,
201 E: crate::error::ParserError<Self>,
202{
203 fn record_err(
204 &mut self,
205 token_start: &Self::Checkpoint,
206 err_start: &Self::Checkpoint,
207 err: E,
208 ) -> Result<(), E> {
209 if self.is_recoverable {
210 if err.is_incomplete() {
211 Err(err)
212 } else {
213 self.errors
214 .push(R::from_recoverable_error(token_start, err_start, self, err));
215 Ok(())
216 }
217 } else {
218 Err(err)
219 }
220 }
221
222 #[inline(always)]
224 fn is_recovery_supported() -> bool {
225 true
226 }
227}
228
229impl<I, E> StreamIsPartial for Recoverable<I, E>
230where
231 I: StreamIsPartial,
232 I: Stream,
233{
234 type PartialState = I::PartialState;
235
236 #[inline]
237 fn complete(&mut self) -> Self::PartialState {
238 self.input.complete()
239 }
240
241 #[inline]
242 fn restore_partial(&mut self, state: Self::PartialState) {
243 self.input.restore_partial(state);
244 }
245
246 #[inline(always)]
247 fn is_partial_supported() -> bool {
248 I::is_partial_supported()
249 }
250
251 #[inline(always)]
252 fn is_partial(&self) -> bool {
253 self.input.is_partial()
254 }
255}
256
257impl<I, E> Offset for Recoverable<I, E>
258where
259 I: Stream,
260 E: crate::lib::std::fmt::Debug,
261{
262 #[inline(always)]
263 fn offset_from(&self, other: &Self) -> usize {
264 self.offset_from(&other.checkpoint())
265 }
266}
267
268impl<I, E> Offset<<Recoverable<I, E> as Stream>::Checkpoint> for Recoverable<I, E>
269where
270 I: Stream,
271 E: crate::lib::std::fmt::Debug,
272{
273 #[inline(always)]
274 fn offset_from(&self, other: &<Recoverable<I, E> as Stream>::Checkpoint) -> usize {
275 self.checkpoint().offset_from(other)
276 }
277}
278
279impl<I, E> AsBytes for Recoverable<I, E>
280where
281 I: Stream,
282 I: AsBytes,
283{
284 #[inline(always)]
285 fn as_bytes(&self) -> &[u8] {
286 self.input.as_bytes()
287 }
288}
289
290impl<I, E> AsBStr for Recoverable<I, E>
291where
292 I: Stream,
293 I: AsBStr,
294{
295 #[inline(always)]
296 fn as_bstr(&self) -> &[u8] {
297 self.input.as_bstr()
298 }
299}
300
301impl<I, E, U> Compare<U> for Recoverable<I, E>
302where
303 I: Stream,
304 I: Compare<U>,
305{
306 #[inline(always)]
307 fn compare(&self, other: U) -> CompareResult {
308 self.input.compare(other)
309 }
310}
311
312impl<I, E, T> FindSlice<T> for Recoverable<I, E>
313where
314 I: Stream,
315 I: FindSlice<T>,
316{
317 #[inline(always)]
318 fn find_slice(&self, substr: T) -> Option<crate::lib::std::ops::Range<usize>> {
319 self.input.find_slice(substr)
320 }
321}
322
323impl<I, E> UpdateSlice for Recoverable<I, E>
324where
325 I: Stream,
326 I: UpdateSlice,
327 E: crate::lib::std::fmt::Debug,
328{
329 #[inline(always)]
330 fn update_slice(mut self, inner: Self::Slice) -> Self {
331 self.input = I::update_slice(self.input, inner);
332 self
333 }
334}