Collect errors into a single error

This commit is contained in:
Paul Hauner 2019-07-06 15:57:11 +10:00
parent 2b7d5560ad
commit c8c5c8ff16
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
4 changed files with 28 additions and 49 deletions

View File

@ -1,4 +1,4 @@
use crate::FixedSizedError; use crate::Error;
use bit_reverse::LookupReverse; use bit_reverse::LookupReverse;
use bit_vec::BitVec as Bitfield; use bit_vec::BitVec as Bitfield;
use serde::de::{Deserialize, Deserializer}; use serde::de::{Deserialize, Deserializer};
@ -12,10 +12,10 @@ use typenum::Unsigned;
/// Provides a common `impl` for structs that wrap a `$name`. /// Provides a common `impl` for structs that wrap a `$name`.
macro_rules! common_impl { macro_rules! common_impl {
($name: ident, $error: ident) => { ($name: ident) => {
impl<N: Unsigned> $name<N> { impl<N: Unsigned> $name<N> {
/// Create a new BitList list with `initial_len` bits all set to `false`. /// Create a new BitList list with `initial_len` bits all set to `false`.
pub fn with_capacity(initial_len: usize) -> Result<Self, $error> { pub fn with_capacity(initial_len: usize) -> Result<Self, Error> {
Self::from_elem(initial_len, false) Self::from_elem(initial_len, false)
} }
@ -23,7 +23,7 @@ macro_rules! common_impl {
/// ///
/// Note: if `initial_len` is not a multiple of 8, the remaining bits will be set to `false` /// Note: if `initial_len` is not a multiple of 8, the remaining bits will be set to `false`
/// regardless of `bit`. /// regardless of `bit`.
pub fn from_elem(initial_len: usize, bit: bool) -> Result<Self, $error> { pub fn from_elem(initial_len: usize, bit: bool) -> Result<Self, Error> {
// BitVec can panic if we don't set the len to be a multiple of 8. // BitVec can panic if we don't set the len to be a multiple of 8.
let full_len = ((initial_len + 7) / 8) * 8; let full_len = ((initial_len + 7) / 8) * 8;
@ -44,7 +44,7 @@ macro_rules! common_impl {
} }
/// Create a new bitfield using the supplied `bytes` as input /// Create a new bitfield using the supplied `bytes` as input
pub fn from_bytes(bytes: &[u8]) -> Result<Self, $error> { pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
Self::validate_length(bytes.len().saturating_mul(8))?; Self::validate_length(bytes.len().saturating_mul(8))?;
Ok(Self { Ok(Self {
@ -62,17 +62,17 @@ macro_rules! common_impl {
/// If the index is in bounds, then result is Ok(value) where value is `true` if the /// If the index is in bounds, then result is Ok(value) where value is `true` if the
/// bit is 1 and `false` if the bit is 0. If the index is out of bounds, we return an /// bit is 1 and `false` if the bit is 0. If the index is out of bounds, we return an
/// error to that extent. /// error to that extent.
pub fn get(&self, i: usize) -> Result<bool, $error> { pub fn get(&self, i: usize) -> Result<bool, Error> {
if i < N::to_usize() { if i < N::to_usize() {
match self.bitfield.get(i) { match self.bitfield.get(i) {
Some(value) => Ok(value), Some(value) => Ok(value),
None => Err($error::OutOfBounds { None => Err(Error::OutOfBounds {
i, i,
len: self.bitfield.len(), len: self.bitfield.len(),
}), }),
} }
} else { } else {
Err($error::InvalidLength { Err(Error::InvalidLength {
i, i,
len: N::to_usize(), len: N::to_usize(),
}) })
@ -83,10 +83,10 @@ macro_rules! common_impl {
/// ///
/// If the index is out of bounds, we expand the size of the underlying set to include /// If the index is out of bounds, we expand the size of the underlying set to include
/// the new index. Returns the previous value if there was one. /// the new index. Returns the previous value if there was one.
pub fn set(&mut self, i: usize, value: bool) -> Result<(), $error> { pub fn set(&mut self, i: usize, value: bool) -> Result<(), Error> {
match self.get(i) { match self.get(i) {
Ok(previous) => Some(previous), Ok(previous) => Some(previous),
Err($error::OutOfBounds { len, .. }) => { Err(Error::OutOfBounds { len, .. }) => {
let new_len = i - len + 1; let new_len = i - len + 1;
self.bitfield.grow(new_len, false); self.bitfield.grow(new_len, false);
None None
@ -266,7 +266,7 @@ pub struct BitVector<N> {
_phantom: PhantomData<N>, _phantom: PhantomData<N>,
} }
common_impl!(BitVector, FixedSizedError); common_impl!(BitVector);
impl<N: Unsigned> BitVector<N> { impl<N: Unsigned> BitVector<N> {
/// Create a new bitfield. /// Create a new bitfield.
@ -278,11 +278,11 @@ impl<N: Unsigned> BitVector<N> {
N::to_usize() N::to_usize()
} }
fn validate_length(len: usize) -> Result<(), FixedSizedError> { fn validate_length(len: usize) -> Result<(), Error> {
let fixed_len = N::to_usize(); let fixed_len = N::to_usize();
if len > fixed_len { if len > fixed_len {
Err(FixedSizedError::InvalidLength { Err(Error::InvalidLength {
i: len, i: len,
len: fixed_len, len: fixed_len,
}) })
@ -329,7 +329,7 @@ pub struct BitList<N> {
_phantom: PhantomData<N>, _phantom: PhantomData<N>,
} }
common_impl!(BitList, FixedSizedError); common_impl!(BitList);
impl<N: Unsigned> BitList<N> { impl<N: Unsigned> BitList<N> {
/// Create a new, empty BitList. /// Create a new, empty BitList.
@ -340,11 +340,11 @@ impl<N: Unsigned> BitList<N> {
} }
} }
fn validate_length(len: usize) -> Result<(), FixedSizedError> { fn validate_length(len: usize) -> Result<(), Error> {
let max_len = Self::max_len(); let max_len = Self::max_len();
if len > max_len { if len > max_len {
Err(FixedSizedError::InvalidLength { Err(Error::InvalidLength {
i: len, i: len,
len: max_len, len: max_len,
}) })

View File

@ -1,4 +1,4 @@
use crate::FixedSizedError as Error; use crate::Error;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::{Deref, Index, IndexMut}; use std::ops::{Deref, Index, IndexMut};

View File

@ -7,30 +7,9 @@ pub use fixed_vector::FixedVector;
pub use typenum; pub use typenum;
pub use variable_list::VariableList; pub use variable_list::VariableList;
/// Returned when a variable-length item encounters an error. /// Returned when an item encounters an error.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub enum VariableSizedError { pub enum Error {
/// The operation would cause the maximum length to be exceeded. InvalidLength { i: usize, len: usize },
ExceedsMaxLength { OutOfBounds { i: usize, len: usize },
len: usize,
max_len: usize,
},
OutOfBounds {
i: usize,
len: usize,
},
}
/// Returned when a fixed-length item encounters an error.
#[derive(PartialEq, Debug)]
pub enum FixedSizedError {
/// The operation would create an item of an invalid size.
InvalidLength {
i: usize,
len: usize,
},
OutOfBounds {
i: usize,
len: usize,
},
} }

View File

@ -1,4 +1,4 @@
use crate::VariableSizedError as Error; use crate::Error;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::{Deref, Index, IndexMut}; use std::ops::{Deref, Index, IndexMut};
@ -61,9 +61,9 @@ impl<T, N: Unsigned> VariableList<T, N> {
_phantom: PhantomData, _phantom: PhantomData,
}) })
} else { } else {
Err(Error::ExceedsMaxLength { Err(Error::InvalidLength {
len: vec.len(), i: vec.len(),
max_len: Self::max_len(), len: Self::max_len(),
}) })
} }
} }
@ -90,9 +90,9 @@ impl<T, N: Unsigned> VariableList<T, N> {
if self.vec.len() < Self::max_len() { if self.vec.len() < Self::max_len() {
Ok(self.vec.push(value)) Ok(self.vec.push(value))
} else { } else {
Err(Error::ExceedsMaxLength { Err(Error::InvalidLength {
len: self.vec.len() + 1, i: self.vec.len() + 1,
max_len: Self::max_len(), len: Self::max_len(),
}) })
} }
} }