rkyv_test/util/
mod.rs

1//! Utilities for common archive operations.
2//!
3//! ## Buffer access
4//!
5//! Helper functions to get the root object of an archive under certain conditions.
6//!
7//! ## Alignment
8//!
9//! Alignment helpers ensure that byte buffers are properly aligned when accessing and deserializing
10//! data.
11
12#[cfg(feature = "alloc")]
13mod aligned_vec;
14mod scratch_vec;
15
16#[cfg(feature = "alloc")]
17use crate::{
18    de::deserializers::SharedDeserializeMap,
19    ser::{serializers::AllocSerializer, Serializer},
20    Deserialize, Fallible, Serialize,
21};
22use crate::{Archive, ArchiveUnsized, RelPtr};
23use core::{
24    mem,
25    ops::{Deref, DerefMut},
26    pin::Pin,
27};
28
29#[doc(inline)]
30#[cfg(feature = "alloc")]
31pub use self::aligned_vec::*;
32#[doc(inline)]
33pub use self::scratch_vec::*;
34
35#[cfg(debug_assertions)]
36#[inline]
37fn check_alignment<T>(ptr: *const u8) {
38    let expect_align = core::mem::align_of::<T>();
39    let actual_align = (ptr as usize) & (expect_align - 1);
40    debug_assert_eq!(
41        actual_align,
42        0,
43        concat!(
44            "unaligned buffer, expected alignment {} but found alignment {}\n",
45            "help: rkyv requires byte buffers to be aligned to access the data inside.\n",
46            "      Using an ALignedVec or manually aligning your data with #[align(...)]\n",
47            "      may resolve this issue.",
48        ),
49        expect_align,
50        1 << actual_align.trailing_zeros()
51    );
52}
53
54/// Casts an archived value from the given byte slice at the given position.
55///
56/// This helps avoid situations where lifetimes get inappropriately assigned and allow buffer
57/// mutation after getting archived value references.
58///
59/// # Safety
60///
61/// A `T::Archived` must be archived at the given position in the byte slice.
62#[inline]
63pub unsafe fn archived_value<T: Archive + ?Sized>(bytes: &[u8], pos: usize) -> &T::Archived {
64    #[cfg(debug_assertions)]
65    check_alignment::<T::Archived>(bytes.as_ptr());
66
67    &*bytes.as_ptr().add(pos).cast()
68}
69
70/// Casts a mutable archived value from the given byte slice at the given position.
71///
72/// This helps avoid situations where lifetimes get inappropriately assigned and allow buffer
73/// mutation after getting archived value references.
74///
75/// # Safety
76///
77/// A `T::Archived` must be archived at the given position in the byte slice.
78#[inline]
79pub unsafe fn archived_value_mut<T: Archive + ?Sized>(
80    bytes: Pin<&mut [u8]>,
81    pos: usize,
82) -> Pin<&mut T::Archived> {
83    #[cfg(debug_assertions)]
84    check_alignment::<T::Archived>(bytes.as_ptr());
85
86    Pin::new_unchecked(&mut *bytes.get_unchecked_mut().as_mut_ptr().add(pos).cast())
87}
88
89/// Casts a [`RelPtr`] to the given unsized type from the given byte slice at the given position and
90/// returns the value it points to.
91///
92/// This helps avoid situations where lifetimes get inappropriately assigned and allow buffer
93/// mutation after getting archived value references.
94///
95/// # Safety
96///
97/// A `RelPtr<T::Archived>` must be archived at the given position in the byte slice.
98#[inline]
99pub unsafe fn archived_unsized_value<T: ArchiveUnsized + ?Sized>(
100    bytes: &[u8],
101    pos: usize,
102) -> &T::Archived {
103    #[cfg(debug_assertions)]
104    check_alignment::<RelPtr<T::Archived>>(bytes.as_ptr());
105
106    let rel_ptr = &*bytes.as_ptr().add(pos).cast::<RelPtr<T::Archived>>();
107    &*rel_ptr.as_ptr()
108}
109
110/// Casts a mutable [`RelPtr`] to the given unsized type from the given byte slice at the given
111/// position and returns the value it points to.
112///
113/// This helps avoid situations where lifetimes get inappropriately assigned and allow buffer
114/// mutation after getting archived value references.
115///
116/// # Safety
117///
118/// A `RelPtr<T::Archived>` must be archived at the given position in the byte slice.
119#[inline]
120pub unsafe fn archived_unsized_value_mut<T: ArchiveUnsized + ?Sized>(
121    bytes: Pin<&mut [u8]>,
122    pos: usize,
123) -> Pin<&mut T::Archived> {
124    #[cfg(debug_assertions)]
125    check_alignment::<RelPtr<T::Archived>>(bytes.as_ptr());
126
127    let rel_ptr = &mut *bytes
128        .get_unchecked_mut()
129        .as_mut_ptr()
130        .add(pos)
131        .cast::<RelPtr<T::Archived>>();
132    Pin::new_unchecked(&mut *rel_ptr.as_mut_ptr())
133}
134
135/// Casts an archived value from the given byte slice by calculating the root position.
136///
137/// This is a wrapper for [`archived_value`](crate::archived_value) that calculates the correct
138/// position of the root using the length of the byte slice. If your byte slice is not guaranteed to
139/// end immediately after the root object, you may need to store the position of the root object
140/// returned from [`serialize_value`](crate::ser::Serializer::serialize_value).
141///
142/// # Safety
143///
144/// - The byte slice must represent an archived object
145/// - The root of the object must be stored at the end of the slice (this is the default behavior)
146#[inline]
147pub unsafe fn archived_root<T: Archive + ?Sized>(bytes: &[u8]) -> &T::Archived {
148    archived_value::<T>(bytes, bytes.len() - mem::size_of::<T::Archived>())
149}
150
151/// Casts a mutable archived value from the given byte slice by calculating the root position.
152///
153/// This is a wrapper for [`archived_value_mut`](crate::archived_value_mut) that calculates the
154/// correct position of the root using the length of the byte slice. If your byte slice is not
155/// guaranteed to end immediately after the root object, you may need to store the position of the
156/// root object returned from [`serialize_value`](crate::ser::Serializer::serialize_value).
157///
158/// # Safety
159///
160/// - The byte slice must represent an archived object
161/// - The root of the object must be stored at the end of the slice (this is the default behavior)
162#[inline]
163pub unsafe fn archived_root_mut<T: Archive + ?Sized>(
164    bytes: Pin<&mut [u8]>,
165) -> Pin<&mut T::Archived> {
166    let pos = bytes.len() - mem::size_of::<T::Archived>();
167    archived_value_mut::<T>(bytes, pos)
168}
169
170/// Casts a [`RelPtr`] to the given unsized type from the given byte slice by calculating the root
171/// position.
172///
173/// This is a wrapper for [`archived_unsized_value`](crate::archived_unsized_value) that calculates
174/// the correct position of the root using the length of the byte slice. If your byte slice is not
175/// guaranteed to end immediately after the root object, you may need to store the position of the
176/// root object returned from
177/// [`serialize_unsized_value`](crate::ser::Serializer::serialize_unsized_value).
178///
179/// # Safety
180///
181/// - The byte slice must represent an archived object
182/// - The root of the object must be stored at the end of the slice (this is the default behavior)
183#[inline]
184pub unsafe fn archived_unsized_root<T: ArchiveUnsized + ?Sized>(bytes: &[u8]) -> &T::Archived {
185    archived_unsized_value::<T>(bytes, bytes.len() - mem::size_of::<RelPtr<T::Archived>>())
186}
187
188/// Casts a [`RelPtr`] to the given unsized type from the given byte slice by calculating the root
189/// position.
190///
191/// This is a wrapper for [`archived_unsized_value_mut`](crate::archived_unsized_value_mut) that
192/// calculates the correct position of the root using the length of the byte slice. If your byte
193/// slice is not guaranteed to end immediately after the root object, you may need to store the
194/// position of the root object returned from
195/// [`serialize_unsized_value`](crate::ser::Serializer::serialize_unsized_value).
196///
197/// # Safety
198///
199/// - The byte slice must represent an archived object
200/// - The root of the object must be stored at the end of the slice (this is the default behavior)
201#[inline]
202pub unsafe fn archived_unsized_root_mut<T: ArchiveUnsized + ?Sized>(
203    bytes: Pin<&mut [u8]>,
204) -> Pin<&mut T::Archived> {
205    let pos = bytes.len() - mem::size_of::<RelPtr<T::Archived>>();
206    archived_unsized_value_mut::<T>(bytes, pos)
207}
208
209/// A buffer of bytes aligned to 16 bytes.
210///
211/// # Examples
212///
213/// ```
214/// use core::mem;
215/// use rkyv::AlignedBytes;
216///
217/// assert_eq!(mem::align_of::<u8>(), 1);
218/// assert_eq!(mem::align_of::<AlignedBytes<256>>(), 16);
219/// ```
220#[derive(Clone, Copy, Debug)]
221#[repr(C, align(16))]
222pub struct AlignedBytes<const N: usize>(pub [u8; N]);
223
224impl<const N: usize> Default for AlignedBytes<N> {
225    fn default() -> Self {
226        Self([0; N])
227    }
228}
229
230impl<const N: usize> Deref for AlignedBytes<N> {
231    type Target = [u8; N];
232
233    #[inline]
234    fn deref(&self) -> &Self::Target {
235        &self.0
236    }
237}
238
239impl<const N: usize> DerefMut for AlignedBytes<N> {
240    #[inline]
241    fn deref_mut(&mut self) -> &mut Self::Target {
242        &mut self.0
243    }
244}
245
246impl<const N: usize> AsRef<[u8]> for AlignedBytes<N> {
247    #[inline]
248    fn as_ref(&self) -> &[u8] {
249        self.0.as_ref()
250    }
251}
252
253impl<const N: usize> AsMut<[u8]> for AlignedBytes<N> {
254    #[inline]
255    fn as_mut(&mut self) -> &mut [u8] {
256        self.0.as_mut()
257    }
258}
259
260/// Serializes the given value and returns the resulting bytes.
261///
262/// The const generic parameter `N` specifies the number of bytes to pre-allocate as scratch space.
263/// Choosing a good default value for your data can be difficult without any data, so consider using
264/// [`ScratchTracker`](crate::ser::serializers::ScratchTracker) to determine how much scratch space
265/// is typically used.
266///
267/// This function is only available with the `alloc` feature because it uses a general-purpose
268/// serializer. In no-alloc and high-performance environments, the serializer should be customized
269/// for the specific situation.
270///
271/// # Examples
272/// ```
273/// let value = vec![1, 2, 3, 4];
274///
275/// let bytes = rkyv::to_bytes::<_, 1024>(&value).expect("failed to serialize vec");
276/// // SAFETY:
277/// // - The byte slice represents an archived object
278/// // - The root of the object is stored at the end of the slice
279/// let deserialized = unsafe {
280///     rkyv::from_bytes_unchecked::<Vec<i32>>(&bytes)
281///         .expect("failed to deserialize vec")
282/// };
283///
284/// assert_eq!(deserialized, value);
285/// ```
286#[cfg(feature = "alloc")]
287#[inline]
288pub fn to_bytes<T, const N: usize>(
289    value: &T,
290) -> Result<AlignedVec, <AllocSerializer<N> as Fallible>::Error>
291where
292    T: Serialize<AllocSerializer<N>>,
293{
294    let mut serializer = AllocSerializer::<N>::default();
295    serializer.serialize_value(value)?;
296    Ok(serializer.into_serializer().into_inner())
297}
298
299/// Deserializes a value from the given bytes.
300///
301/// This function is only available with the `alloc` feature because it uses a general-purpose
302/// deserializer. In no-alloc and high-performance environments, the deserializer should be
303/// customized for the specific situation.
304///
305/// # Safety
306///
307/// - The byte slice must represent an archived object
308/// - The root of the object must be stored at the end of the slice (this is the default behavior)
309///
310/// # Examples
311/// ```
312/// let value = vec![1, 2, 3, 4];
313///
314/// let bytes = rkyv::to_bytes::<_, 1024>(&value).expect("failed to serialize vec");
315/// // SAFETY:
316/// // - The byte slice represents an archived object
317/// // - The root of the object is stored at the end of the slice
318/// let deserialized = unsafe {
319///     rkyv::from_bytes_unchecked::<Vec<i32>>(&bytes)
320///         .expect("failed to deserialize vec")
321/// };
322///
323/// assert_eq!(deserialized, value);
324/// ```
325#[cfg(feature = "alloc")]
326#[inline]
327pub unsafe fn from_bytes_unchecked<T>(
328    bytes: &[u8],
329) -> Result<T, <SharedDeserializeMap as Fallible>::Error>
330where
331    T: Archive,
332    T::Archived: Deserialize<T, SharedDeserializeMap>,
333{
334    archived_root::<T>(bytes).deserialize(&mut SharedDeserializeMap::default())
335}