1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
//! Shared pointer validation.
#[cfg(feature = "alloc")]
mod validator;
use core::any::TypeId;
use rancor::{Fallible, Strategy};
#[cfg(feature = "alloc")]
pub use self::validator::*;
/// The result of starting to validate a shared pointer.
pub enum ValidationState {
/// The caller started validating this value. They should proceed to check
/// the shared value and call `finish_shared`.
Started,
/// Another caller started validating this value, but has not finished yet.
/// This can only occur with cyclic shared pointer structures, and so rkyv
/// treats this as an error by default.
Pending,
/// This value has already been validated.
Finished,
}
/// A context that can validate shared archive memory.
///
/// Shared pointers require this kind of context to validate.
pub trait SharedContext<E = <Self as Fallible>::Error> {
/// Starts validating the value associated with the given address.
///
/// Returns an error if the value associated with the given address was
/// started with a different type ID.
fn start_shared(
&mut self,
address: usize,
type_id: TypeId,
) -> Result<ValidationState, E>;
/// Finishes validating the value associated with the given address.
///
/// Returns an error if the given address was not pending.
fn finish_shared(
&mut self,
address: usize,
type_id: TypeId,
) -> Result<(), E>;
}
impl<T, E> SharedContext<E> for Strategy<T, E>
where
T: SharedContext<E>,
{
fn start_shared(
&mut self,
address: usize,
type_id: TypeId,
) -> Result<ValidationState, E> {
T::start_shared(self, address, type_id)
}
fn finish_shared(
&mut self,
address: usize,
type_id: TypeId,
) -> Result<(), E> {
T::finish_shared(self, address, type_id)
}
}