Function bytecheck::check_bytes_with_context
source · pub unsafe fn check_bytes_with_context<T, C, E>(
value: *const T,
context: &mut C,
) -> Result<(), E>
Expand description
Checks whether the given pointer points to a valid value within the given context.
§Safety
The passed pointer must be aligned and point to enough initialized bytes to represent the type.
§Example
use core::{error::Error, fmt};
use bytecheck::{check_bytes_with_context, CheckBytes, Verify};
use rancor::{fail, Failure, Fallible, Source, Strategy};
trait Context {
fn is_allowed(&self, value: u8) -> bool;
}
impl<T: Context + ?Sized, E> Context for Strategy<T, E> {
fn is_allowed(&self, value: u8) -> bool {
T::is_allowed(self, value)
}
}
struct Allowed(u8);
impl Context for Allowed {
fn is_allowed(&self, value: u8) -> bool {
value == self.0
}
}
#[derive(CheckBytes)]
#[bytecheck(verify)]
#[repr(C)]
pub struct ContextualByte(u8);
unsafe impl<C: Context + Fallible + ?Sized> Verify<C> for ContextualByte
where
C::Error: Source,
{
fn verify(&self, context: &mut C) -> Result<(), C::Error> {
#[derive(Debug)]
struct InvalidByte(u8);
impl fmt::Display for InvalidByte {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "invalid contextual byte: {}", self.0)
}
}
impl Error for InvalidByte {}
if !context.is_allowed(self.0) {
fail!(InvalidByte(self.0));
}
Ok(())
}
}
let value = 45u8;
unsafe {
// Checking passes when the context allows byte 45
check_bytes_with_context::<ContextualByte, _, Failure>(
(&value as *const u8).cast(),
&mut Allowed(45),
)
.unwrap();
// Checking fails when the conteext does not allow byte 45
check_bytes_with_context::<ContextualByte, _, Failure>(
(&value as *const u8).cast(),
&mut Allowed(0),
)
.unwrap_err();
}