Skip to content

Commit

Permalink
Use ULEError for VarZeroVec
Browse files Browse the repository at this point in the history
  • Loading branch information
Manishearth committed Dec 13, 2021
1 parent dd7a5dc commit 1eb37a3
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 94 deletions.
3 changes: 2 additions & 1 deletion utils/zerovec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,6 @@ pub mod zerovec;
mod yoke_impls;

pub use crate::map::ZeroMap;
pub use crate::varzerovec::{VarZeroVec, VarZeroVecError};
pub use crate::varzerovec::VarZeroVec;
pub use crate::zerovec::ZeroVec;
pub use crate::ule::ULEError;
8 changes: 6 additions & 2 deletions utils/zerovec/src/ule/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use core::fmt;
pub enum ULEError {
InvalidLength { ty: &'static str, len: usize },
ParseError { ty: &'static str },
FormatError,
}

impl fmt::Display for ULEError {
Expand All @@ -21,18 +22,21 @@ impl fmt::Display for ULEError {
ULEError::ParseError { ty } => {
write!(f, "Could not parse data as valud {}", ty)
}
ULEError::FormatError => {
write!(f, "Invalid format for VarZeroVec buffer")
}
}
}
}

impl ULEError {
pub fn parse<T: 'static>() -> ULEError {
pub fn parse<T: ?Sized + 'static>() -> ULEError {
ULEError::ParseError {
ty: any::type_name::<T>(),
}
}

pub fn length<T: 'static>(len: usize) -> ULEError {
pub fn length<T: ?Sized + 'static>(len: usize) -> ULEError {
ULEError::InvalidLength {
ty: any::type_name::<T>(),
len,
Expand Down
9 changes: 3 additions & 6 deletions utils/zerovec/src/ule/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use plain::PlainOldULE;
use alloc::alloc::Layout;
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use core::{fmt, mem, slice};
use core::{mem, slice};

/// Fixed-width, byte-aligned data that can be cast to and from a little-endian byte slice.
///
Expand Down Expand Up @@ -260,15 +260,12 @@ where
/// Failure to follow this invariant will cause surprising behavior in `PartialEq`, which may
/// result in unpredictable operations on `ZeroVec`, `VarZeroVec`, and `ZeroMap`.
pub unsafe trait VarULE: 'static {
/// The error that occurs if a byte array is not valid for this ULE.
type Error: fmt::Display;

/// Validates a byte slice, `&[u8]`.
///
/// If `Self` is not well-defined for all possible bit values, the bytes should be validated.
/// If the bytes can be transmuted, *in their entirety*, to a valid `&Self`, then `Ok` should
/// be returned; otherwise, `Self::Error` should be returned.
fn validate_byte_slice(_bytes: &[u8]) -> Result<(), Self::Error>;
fn validate_byte_slice(_bytes: &[u8]) -> Result<(), ULEError>;

/// Parses a byte slice, `&[u8]`, and return it as `&Self` with the same lifetime.
///
Expand All @@ -281,7 +278,7 @@ pub unsafe trait VarULE: 'static {
/// Note: The following equality should hold: `size_of_val(result) == size_of_val(bytes)`,
/// where `result` is the successful return value of the method. This means that the return
/// value spans the entire byte slice.
fn parse_byte_slice(bytes: &[u8]) -> Result<&Self, Self::Error> {
fn parse_byte_slice(bytes: &[u8]) -> Result<&Self, ULEError> {
Self::validate_byte_slice(bytes)?;
let result = unsafe { Self::from_byte_slice_unchecked(bytes) };
debug_assert_eq!(mem::size_of_val(result), mem::size_of_val(bytes));
Expand Down
14 changes: 5 additions & 9 deletions utils/zerovec/src/ule/slices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@ use core::str;
// 6. `parse_byte_slice()` is equivalent to `validate_byte_slice()` followed by `from_byte_slice_unchecked()`
// 7. str byte equality is semantic equality
unsafe impl VarULE for str {
type Error = str::Utf8Error;

#[inline]
fn validate_byte_slice(bytes: &[u8]) -> Result<(), Self::Error> {
str::from_utf8(bytes)?;
fn validate_byte_slice(bytes: &[u8]) -> Result<(), ULEError> {
str::from_utf8(bytes).map_err(|_| ULEError::parse::<Self>())?;
Ok(())
}

#[inline]
fn parse_byte_slice(bytes: &[u8]) -> Result<&Self, Self::Error> {
str::from_utf8(bytes)
fn parse_byte_slice(bytes: &[u8]) -> Result<&Self, ULEError> {
str::from_utf8(bytes).map_err(|_| ULEError::parse::<Self>())
}
/// Invariant: must be safe to call when called on a slice that previously
/// succeeded with `parse_byte_slice`
Expand All @@ -46,10 +44,8 @@ unsafe impl<T> VarULE for [T]
where
T: ULE + AsULE<ULE = T>,
{
type Error = ULEError;

#[inline]
fn validate_byte_slice(slice: &[u8]) -> Result<(), Self::Error> {
fn validate_byte_slice(slice: &[u8]) -> Result<(), ULEError> {
T::validate_byte_slice(slice)
}

Expand Down
35 changes: 12 additions & 23 deletions utils/zerovec/src/varzerovec/borrowed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl<'a, T: VarULE + ?Sized> VarZeroVecBorrowed<'a, T> {
/// - `indices[len - 1]..things.len()` must index into a valid section of
/// `things`, such that it parses to a `T::VarULE`
#[inline]
pub fn parse_byte_slice(slice: &'a [u8]) -> Result<Self, ParseErrorFor<T>> {
pub fn parse_byte_slice(slice: &'a [u8]) -> Result<Self, ULEError> {
if slice.is_empty() {
return Ok(VarZeroVecBorrowed {
indices: &[],
Expand All @@ -98,20 +98,15 @@ impl<'a, T: VarULE + ?Sized> VarZeroVecBorrowed<'a, T> {
marker: PhantomData,
});
}
let len_bytes = slice.get(0..4).ok_or(VarZeroVecError::FormatError)?;
let len_ule = PlainOldULE::<4>::parse_byte_slice(len_bytes)
.map_err(|_| VarZeroVecError::FormatError)?;
let len_bytes = slice.get(0..4).ok_or(ULEError::FormatError)?;
let len_ule =
PlainOldULE::<4>::parse_byte_slice(len_bytes).map_err(|_| ULEError::FormatError)?;

let len =
u32::from_unaligned(*len_ule.get(0).ok_or(VarZeroVecError::FormatError)?) as usize;
let indices_bytes = slice
.get(4..4 * len + 4)
.ok_or(VarZeroVecError::FormatError)?;
let indices = PlainOldULE::<4>::parse_byte_slice(indices_bytes)
.map_err(|_| VarZeroVecError::FormatError)?;
let things = slice
.get(4 * len + 4..)
.ok_or(VarZeroVecError::FormatError)?;
let len = u32::from_unaligned(*len_ule.get(0).ok_or(ULEError::FormatError)?) as usize;
let indices_bytes = slice.get(4..4 * len + 4).ok_or(ULEError::FormatError)?;
let indices =
PlainOldULE::<4>::parse_byte_slice(indices_bytes).map_err(|_| ULEError::FormatError)?;
let things = slice.get(4 * len + 4..).ok_or(ULEError::FormatError)?;

let borrowed = VarZeroVecBorrowed {
indices,
Expand Down Expand Up @@ -215,16 +210,12 @@ impl<'a, T: VarULE + ?Sized> VarZeroVecBorrowed<'a, T> {
/// This method is NOT allowed to call any other methods on VarZeroVecBorrowed since all other methods
/// assume that the slice has been passed through iter_checked
#[inline]
fn iter_checked(self) -> impl Iterator<Item = Result<&'a T, ParseErrorFor<T>>> {
fn iter_checked(self) -> impl Iterator<Item = Result<&'a T, ULEError>> {
let last = iter::from_fn(move || {
if !self.is_empty() {
let start = usizeify(self.indices[self.len() - 1]);
let end = self.things.len();
Some(
self.things
.get(start..end)
.ok_or(VarZeroVecError::FormatError),
)
Some(self.things.get(start..end).ok_or(ULEError::FormatError))
} else {
None
}
Expand All @@ -236,9 +227,7 @@ impl<'a, T: VarULE + ?Sized> VarZeroVecBorrowed<'a, T> {
let start = usizeify(win[0]);
let end = usizeify(win[1]);
// the .get() here automatically verifies that end>=start
self.things
.get(start..end)
.ok_or(VarZeroVecError::FormatError)
self.things.get(start..end).ok_or(ULEError::FormatError)
})
.chain(last)
.map(|s| s.and_then(|s| T::parse_byte_slice(s).map_err(|e| e.into())))
Expand Down
Loading

0 comments on commit 1eb37a3

Please sign in to comment.