rkyv/validation/validators/
mod.rs

1//! Validators that can check archived types.
2
3mod archive;
4mod shared;
5mod util;
6
7use crate::{
8    validation::{
9        check_archived_root_with_context, check_archived_value_with_context, ArchiveContext,
10        CheckTypeError, SharedContext,
11    },
12    Archive, Fallible,
13};
14pub use archive::*;
15use bytecheck::CheckBytes;
16use core::{
17    alloc::{Layout, LayoutError},
18    any::TypeId,
19    fmt,
20};
21pub use shared::*;
22pub use util::*;
23
24/// The default validator error.
25#[derive(Debug)]
26pub enum DefaultValidatorError {
27    /// An archive validator error occurred.
28    ArchiveError(ArchiveError),
29    /// A shared validator error occurred.
30    SharedError(SharedError),
31}
32
33impl fmt::Display for DefaultValidatorError {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        match self {
36            Self::ArchiveError(e) => write!(f, "{}", e),
37            Self::SharedError(e) => write!(f, "{}", e),
38        }
39    }
40}
41
42#[cfg(feature = "std")]
43const _: () = {
44    use std::error::Error;
45
46    impl Error for DefaultValidatorError {
47        fn source(&self) -> Option<&(dyn Error + 'static)> {
48            match self {
49                Self::ArchiveError(e) => Some(e as &dyn Error),
50                Self::SharedError(e) => Some(e as &dyn Error),
51            }
52        }
53    }
54};
55
56/// The default validator.
57#[derive(Debug)]
58pub struct DefaultValidator<'a> {
59    archive: ArchiveValidator<'a>,
60    shared: SharedValidator,
61}
62
63impl<'a> DefaultValidator<'a> {
64    /// Creates a new validator from a byte range.
65    #[inline]
66    pub fn new(bytes: &'a [u8]) -> Self {
67        Self {
68            archive: ArchiveValidator::new(bytes),
69            shared: SharedValidator::new(),
70        }
71    }
72
73    /// Create a new validator from a byte range with specific capacity.
74    #[inline]
75    pub fn with_capacity(bytes: &'a [u8], capacity: usize) -> Self {
76        Self {
77            archive: ArchiveValidator::new(bytes),
78            shared: SharedValidator::with_capacity(capacity),
79        }
80    }
81}
82
83impl<'a> Fallible for DefaultValidator<'a> {
84    type Error = DefaultValidatorError;
85}
86
87impl<'a> ArchiveContext for DefaultValidator<'a> {
88    type PrefixRange = <ArchiveValidator<'a> as ArchiveContext>::PrefixRange;
89    type SuffixRange = <ArchiveValidator<'a> as ArchiveContext>::SuffixRange;
90
91    #[inline]
92    unsafe fn bounds_check_ptr(
93        &mut self,
94        base: *const u8,
95        offset: isize,
96    ) -> Result<*const u8, Self::Error> {
97        self.archive
98            .bounds_check_ptr(base, offset)
99            .map_err(DefaultValidatorError::ArchiveError)
100    }
101
102    #[inline]
103    unsafe fn bounds_check_layout(
104        &mut self,
105        data_address: *const u8,
106        layout: &Layout,
107    ) -> Result<(), Self::Error> {
108        self.archive
109            .bounds_check_layout(data_address, layout)
110            .map_err(DefaultValidatorError::ArchiveError)
111    }
112
113    #[inline]
114    unsafe fn bounds_check_subtree_ptr_layout(
115        &mut self,
116        data_address: *const u8,
117        layout: &Layout,
118    ) -> Result<(), Self::Error> {
119        self.archive
120            .bounds_check_subtree_ptr_layout(data_address, layout)
121            .map_err(DefaultValidatorError::ArchiveError)
122    }
123
124    #[inline]
125    unsafe fn push_prefix_subtree_range(
126        &mut self,
127        root: *const u8,
128        end: *const u8,
129    ) -> Result<PrefixRange, Self::Error> {
130        self.archive
131            .push_prefix_subtree_range(root, end)
132            .map_err(DefaultValidatorError::ArchiveError)
133    }
134
135    #[inline]
136    fn pop_prefix_range(&mut self, range: PrefixRange) -> Result<(), Self::Error> {
137        self.archive
138            .pop_prefix_range(range)
139            .map_err(DefaultValidatorError::ArchiveError)
140    }
141
142    #[inline]
143    unsafe fn push_suffix_subtree_range(
144        &mut self,
145        start: *const u8,
146        root: *const u8,
147    ) -> Result<SuffixRange, Self::Error> {
148        self.archive
149            .push_suffix_subtree_range(start, root)
150            .map_err(DefaultValidatorError::ArchiveError)
151    }
152
153    #[inline]
154    fn pop_suffix_range(&mut self, range: SuffixRange) -> Result<(), Self::Error> {
155        self.archive
156            .pop_suffix_range(range)
157            .map_err(DefaultValidatorError::ArchiveError)
158    }
159
160    #[inline]
161    fn finish(&mut self) -> Result<(), Self::Error> {
162        self.archive
163            .finish()
164            .map_err(DefaultValidatorError::ArchiveError)
165    }
166
167    #[inline]
168    fn wrap_layout_error(error: LayoutError) -> Self::Error {
169        DefaultValidatorError::ArchiveError(ArchiveValidator::wrap_layout_error(error))
170    }
171}
172
173impl<'a> SharedContext for DefaultValidator<'a> {
174    #[inline]
175    fn register_shared_ptr(
176        &mut self,
177        ptr: *const u8,
178        type_id: TypeId,
179    ) -> Result<bool, Self::Error> {
180        self.shared
181            .register_shared_ptr(ptr, type_id)
182            .map_err(DefaultValidatorError::SharedError)
183    }
184}
185
186/// Checks the given archive at the given position for an archived version of the given type.
187///
188/// This is a safe alternative to [`archived_value`](crate::archived_value) for types that implement
189/// `CheckBytes`.
190///
191/// # Examples
192/// ```
193/// use rkyv::{
194///     check_archived_value,
195///     ser::{Serializer, serializers::AlignedSerializer},
196///     AlignedVec,
197///     Archive,
198///     Serialize,
199/// };
200/// use bytecheck::CheckBytes;
201///
202/// #[derive(Archive, Serialize)]
203/// #[archive_attr(derive(CheckBytes))]
204/// struct Example {
205///     name: String,
206///     value: i32,
207/// }
208///
209/// let value = Example {
210///     name: "pi".to_string(),
211///     value: 31415926,
212/// };
213///
214/// let mut serializer = AlignedSerializer::new(AlignedVec::new());
215/// let pos = serializer.serialize_value(&value)
216///     .expect("failed to archive test");
217/// let buf = serializer.into_inner();
218/// let archived = check_archived_value::<Example>(buf.as_ref(), pos).unwrap();
219/// ```
220#[inline]
221pub fn check_archived_value<'a, T: Archive>(
222    bytes: &'a [u8],
223    pos: usize,
224) -> Result<&T::Archived, CheckTypeError<T::Archived, DefaultValidator<'a>>>
225where
226    T::Archived: CheckBytes<DefaultValidator<'a>>,
227{
228    let mut validator = DefaultValidator::new(bytes);
229    check_archived_value_with_context::<T, DefaultValidator>(bytes, pos, &mut validator)
230}
231
232/// Checks the given archive at the given position for an archived version of the given type.
233///
234/// This is a safe alternative to [`archived_value`](crate::archived_value) for types that implement
235/// `CheckBytes`.
236///
237/// See [`check_archived_value`] for more details.
238#[inline]
239pub fn check_archived_root<'a, T: Archive>(
240    bytes: &'a [u8],
241) -> Result<&'a T::Archived, CheckTypeError<T::Archived, DefaultValidator<'a>>>
242where
243    T::Archived: CheckBytes<DefaultValidator<'a>>,
244{
245    let mut validator = DefaultValidator::new(bytes);
246    check_archived_root_with_context::<T, DefaultValidator>(bytes, &mut validator)
247}