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