Skip to content

Commit e99e9d3

Browse files
committed
Return None after stream deserializer has failed
1 parent a1b1199 commit e99e9d3

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

src/de.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ impl<'de, R: Read<'de>> Deserializer<R> {
151151
StreamDeserializer {
152152
de: self,
153153
offset: offset,
154+
failed: false,
154155
output: PhantomData,
155156
lifetime: PhantomData,
156157
}
@@ -2046,6 +2047,7 @@ where
20462047
pub struct StreamDeserializer<'de, R, T> {
20472048
de: Deserializer<R>,
20482049
offset: usize,
2050+
failed: bool,
20492051
output: PhantomData<T>,
20502052
lifetime: PhantomData<&'de ()>,
20512053
}
@@ -2068,6 +2070,7 @@ where
20682070
StreamDeserializer {
20692071
de: Deserializer::new(read),
20702072
offset: offset,
2073+
failed: false,
20712074
output: PhantomData,
20722075
lifetime: PhantomData,
20732076
}
@@ -2132,6 +2135,10 @@ where
21322135
type Item = Result<T>;
21332136

21342137
fn next(&mut self) -> Option<Result<T>> {
2138+
if R::should_early_return_if_failed && self.failed {
2139+
return None;
2140+
}
2141+
21352142
// skip whitespaces, if any
21362143
// this helps with trailing whitespaces, since whitespaces between
21372144
// values are handled for us.
@@ -2160,10 +2167,16 @@ where
21602167
self.peek_end_of_value().map(|_| value)
21612168
}
21622169
}
2163-
Err(e) => Err(e),
2170+
Err(e) => {
2171+
self.de.read.set_failed(&mut self.failed);
2172+
Err(e)
2173+
}
21642174
})
21652175
}
2166-
Err(e) => Some(Err(e)),
2176+
Err(e) => {
2177+
self.de.read.set_failed(&mut self.failed);
2178+
Some(Err(e))
2179+
}
21672180
}
21682181
}
21692182
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@
337337
clippy::missing_errors_doc,
338338
clippy::must_use_candidate,
339339
)]
340+
#![allow(non_upper_case_globals)]
340341
#![deny(missing_docs)]
341342
#![cfg_attr(not(feature = "std"), no_std)]
342343

src/read.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ pub trait Read<'de>: private::Sealed {
9797
fn end_raw_buffering<V>(&mut self, visitor: V) -> Result<V::Value>
9898
where
9999
V: Visitor<'de>;
100+
101+
/// Whether StreamDeserializer::next needs to check the failed flag. True
102+
/// for IoRead, false for StrRead and SliceRead which can track failure by
103+
/// truncating their input slice to avoid the extra check on every next
104+
/// call.
105+
#[doc(hidden)]
106+
const should_early_return_if_failed: bool;
107+
108+
/// Mark a persistent failure of StreamDeserializer, either by setting the
109+
/// flag or by truncating the input data.
110+
#[doc(hidden)]
111+
fn set_failed(&mut self, failed: &mut bool);
100112
}
101113

102114
pub struct Position {
@@ -379,6 +391,13 @@ where
379391
raw_value: Some(raw),
380392
})
381393
}
394+
395+
const should_early_return_if_failed: bool = true;
396+
397+
#[inline]
398+
fn set_failed(&mut self, failed: &mut bool) {
399+
*failed = true;
400+
}
382401
}
383402

384403
//////////////////////////////////////////////////////////////////////////////
@@ -590,6 +609,13 @@ impl<'a> Read<'a> for SliceRead<'a> {
590609
raw_value: Some(raw),
591610
})
592611
}
612+
613+
const should_early_return_if_failed: bool = false;
614+
615+
#[inline]
616+
fn set_failed(&mut self, _failed: &mut bool) {
617+
self.slice = &self.slice[..self.index];
618+
}
593619
}
594620

595621
//////////////////////////////////////////////////////////////////////////////
@@ -681,6 +707,13 @@ impl<'a> Read<'a> for StrRead<'a> {
681707
raw_value: Some(raw),
682708
})
683709
}
710+
711+
const should_early_return_if_failed: bool = false;
712+
713+
#[inline]
714+
fn set_failed(&mut self, failed: &mut bool) {
715+
self.delegate.set_failed(failed);
716+
}
684717
}
685718

686719
//////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)