Add encode::Error::MissingData variant
The `io::Error` is troublesome because it contains a bunch of stuff that never happens when reading from a buffer. However the EOF variant can occur if the buffer is too short. As an initial step towards reducing usage of the `io::Error` add a `MissingData` variant to the `encode::Error` and when converting from an IO error map to `MissingData` if EOF is encountered.
This commit is contained in:
parent
5a42ef2850
commit
b04142c745
|
@ -1027,13 +1027,11 @@ mod tests {
|
||||||
])
|
])
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, ""));
|
|
||||||
|
|
||||||
// Check serialization that `if len > MAX_VEC_SIZE {return err}` isn't inclusive,
|
// Check serialization that `if len > MAX_VEC_SIZE {return err}` isn't inclusive,
|
||||||
// by making sure it fails with IO Error and not an `OversizedVectorAllocation` Error.
|
// by making sure it fails with `MissingData` and not an `OversizedVectorAllocation` Error.
|
||||||
let err =
|
let err =
|
||||||
deserialize::<CheckedData>(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err();
|
deserialize::<CheckedData>(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err();
|
||||||
assert_eq!(discriminant(&err), discriminant(&rand_io_err));
|
assert!(matches!(err, Error::MissingData));
|
||||||
|
|
||||||
test_len_is_max_vec::<u8>();
|
test_len_is_max_vec::<u8>();
|
||||||
test_len_is_max_vec::<BlockHash>();
|
test_len_is_max_vec::<BlockHash>();
|
||||||
|
@ -1055,11 +1053,10 @@ mod tests {
|
||||||
Vec<T>: Decodable,
|
Vec<T>: Decodable,
|
||||||
T: fmt::Debug,
|
T: fmt::Debug,
|
||||||
{
|
{
|
||||||
let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, ""));
|
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
buf.emit_compact_size(super::MAX_VEC_SIZE / mem::size_of::<T>()).unwrap();
|
buf.emit_compact_size(super::MAX_VEC_SIZE / mem::size_of::<T>()).unwrap();
|
||||||
let err = deserialize::<Vec<T>>(&buf).unwrap_err();
|
let err = deserialize::<Vec<T>>(&buf).unwrap_err();
|
||||||
assert_eq!(discriminant(&err), discriminant(&rand_io_err));
|
assert!(matches!(err, Error::MissingData));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -56,6 +56,8 @@ impl<E: fmt::Debug + std::error::Error + 'static> std::error::Error for DecodeEr
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// And I/O error.
|
/// And I/O error.
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
|
/// Missing data (early end of file or slice too short).
|
||||||
|
MissingData, // TODO: Can we add more context?
|
||||||
/// Tried to allocate an oversized vector.
|
/// Tried to allocate an oversized vector.
|
||||||
OversizedVectorAllocation {
|
OversizedVectorAllocation {
|
||||||
/// The capacity requested.
|
/// The capacity requested.
|
||||||
|
@ -86,6 +88,7 @@ impl fmt::Display for Error {
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Io(ref e) => write_err!(f, "IO error"; e),
|
Io(ref e) => write_err!(f, "IO error"; e),
|
||||||
|
MissingData => write!(f, "missing data (early end of file or slice too short)"),
|
||||||
OversizedVectorAllocation { requested: ref r, max: ref m } =>
|
OversizedVectorAllocation { requested: ref r, max: ref m } =>
|
||||||
write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m),
|
write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m),
|
||||||
InvalidChecksum { expected: ref e, actual: ref a } =>
|
InvalidChecksum { expected: ref e, actual: ref a } =>
|
||||||
|
@ -105,7 +108,8 @@ impl std::error::Error for Error {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Io(e) => Some(e),
|
Io(e) => Some(e),
|
||||||
OversizedVectorAllocation { .. }
|
MissingData
|
||||||
|
| OversizedVectorAllocation { .. }
|
||||||
| InvalidChecksum { .. }
|
| InvalidChecksum { .. }
|
||||||
| NonMinimalVarInt
|
| NonMinimalVarInt
|
||||||
| ParseFailed(_)
|
| ParseFailed(_)
|
||||||
|
@ -115,7 +119,14 @@ impl std::error::Error for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
fn from(error: io::Error) -> Self { Error::Io(error) }
|
fn from(e: io::Error) -> Self {
|
||||||
|
use io::ErrorKind;
|
||||||
|
|
||||||
|
match e.kind() {
|
||||||
|
ErrorKind::UnexpectedEof => Error::MissingData,
|
||||||
|
_ => Error::Io(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hex deserialization error.
|
/// Hex deserialization error.
|
||||||
|
|
|
@ -361,6 +361,8 @@ impl<D: fmt::Display> serde::de::Expected for DisplayExpected<D> {
|
||||||
fn consensus_error_into_serde<E: serde::de::Error>(error: ConsensusError) -> E {
|
fn consensus_error_into_serde<E: serde::de::Error>(error: ConsensusError) -> E {
|
||||||
match error {
|
match error {
|
||||||
ConsensusError::Io(error) => panic!("unexpected IO error {:?}", error),
|
ConsensusError::Io(error) => panic!("unexpected IO error {:?}", error),
|
||||||
|
ConsensusError::MissingData =>
|
||||||
|
E::custom("missing data (early end of file or slice too short)"),
|
||||||
ConsensusError::OversizedVectorAllocation { requested, max } => E::custom(format_args!(
|
ConsensusError::OversizedVectorAllocation { requested, max } => E::custom(format_args!(
|
||||||
"the requested allocation of {} items exceeds maximum of {}",
|
"the requested allocation of {} items exceeds maximum of {}",
|
||||||
requested, max
|
requested, max
|
||||||
|
|
Loading…
Reference in New Issue