rkyv/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 Fallible,
21};
22use crate::{Archive, ArchiveUnsized, Deserialize, RelPtr, Serialize};
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`] that calculates the correct position of the root using
138/// the length of the byte slice. If your byte slice is not guaranteed to end immediately after the
139/// root object, you may need to store the position of the root object returned from
140/// [`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`] that calculates the correct position of the root
154/// using the length of the byte slice. If your byte slice is not guaranteed to end immediately
155/// after the root object, you may need to store the position of the root object returned from
156/// [`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`] that calculates the correct position of the
174/// root using the length of the byte slice. If your byte slice is not guaranteed to end immediately
175/// after the root object, you may need to store the position of the root object returned from
176/// [`serialize_unsized_value`](crate::ser::Serializer::serialize_unsized_value).
177///
178/// # Safety
179///
180/// - The byte slice must represent an archived object
181/// - The root of the object must be stored at the end of the slice (this is the default behavior)
182#[inline]
183pub unsafe fn archived_unsized_root<T: ArchiveUnsized + ?Sized>(bytes: &[u8]) -> &T::Archived {
184 archived_unsized_value::<T>(bytes, bytes.len() - mem::size_of::<RelPtr<T::Archived>>())
185}
186
187/// Casts a [`RelPtr`] to the given unsized type from the given byte slice by calculating the root
188/// position.
189///
190/// This is a wrapper for [`archived_unsized_value_mut`] that calculates the correct position of the
191/// root using the length of the byte slice. If your byte slice is not guaranteed to end immediately
192/// after the root object, you may need to store the position of the root object returned from
193/// [`serialize_unsized_value`](crate::ser::Serializer::serialize_unsized_value).
194///
195/// # Safety
196///
197/// - The byte slice must represent an archived object
198/// - The root of the object must be stored at the end of the slice (this is the default behavior)
199#[inline]
200pub unsafe fn archived_unsized_root_mut<T: ArchiveUnsized + ?Sized>(
201 bytes: Pin<&mut [u8]>,
202) -> Pin<&mut T::Archived> {
203 let pos = bytes.len() - mem::size_of::<RelPtr<T::Archived>>();
204 archived_unsized_value_mut::<T>(bytes, pos)
205}
206
207/// A buffer of bytes aligned to 16 bytes.
208///
209/// # Examples
210///
211/// ```
212/// use core::mem;
213/// use rkyv::AlignedBytes;
214///
215/// assert_eq!(mem::align_of::<u8>(), 1);
216/// assert_eq!(mem::align_of::<AlignedBytes<256>>(), 16);
217/// ```
218#[derive(Archive, Clone, Copy, Debug, Deserialize, Serialize)]
219#[archive(crate = "crate")]
220#[repr(C, align(16))]
221pub struct AlignedBytes<const N: usize>(pub [u8; N]);
222
223impl<const N: usize> Default for AlignedBytes<N> {
224 fn default() -> Self {
225 Self([0; N])
226 }
227}
228
229impl<const N: usize> Deref for AlignedBytes<N> {
230 type Target = [u8; N];
231
232 #[inline]
233 fn deref(&self) -> &Self::Target {
234 &self.0
235 }
236}
237
238impl<const N: usize> DerefMut for AlignedBytes<N> {
239 #[inline]
240 fn deref_mut(&mut self) -> &mut Self::Target {
241 &mut self.0
242 }
243}
244
245impl<const N: usize> AsRef<[u8]> for AlignedBytes<N> {
246 #[inline]
247 fn as_ref(&self) -> &[u8] {
248 self.0.as_ref()
249 }
250}
251
252impl<const N: usize> AsMut<[u8]> for AlignedBytes<N> {
253 #[inline]
254 fn as_mut(&mut self) -> &mut [u8] {
255 self.0.as_mut()
256 }
257}
258
259/// Serializes the given value and returns the resulting bytes.
260///
261/// The const generic parameter `N` specifies the number of bytes to pre-allocate as scratch space.
262/// Choosing a good default value for your data can be difficult without any data, so consider using
263/// [`ScratchTracker`](crate::ser::serializers::ScratchTracker) to determine how much scratch space
264/// is typically used.
265///
266/// This function is only available with the `alloc` feature because it uses a general-purpose
267/// serializer. In no-alloc and high-performance environments, the serializer should be customized
268/// for the specific situation.
269///
270/// # Examples
271/// ```
272/// let value = vec![1, 2, 3, 4];
273///
274/// let bytes = rkyv::to_bytes::<_, 1024>(&value).expect("failed to serialize vec");
275/// // SAFETY:
276/// // - The byte slice represents an archived object
277/// // - The root of the object is stored at the end of the slice
278/// let deserialized = unsafe {
279/// rkyv::from_bytes_unchecked::<Vec<i32>>(&bytes)
280/// .expect("failed to deserialize vec")
281/// };
282///
283/// assert_eq!(deserialized, value);
284/// ```
285#[cfg(feature = "alloc")]
286#[inline]
287pub fn to_bytes<T, const N: usize>(
288 value: &T,
289) -> Result<AlignedVec, <AllocSerializer<N> as Fallible>::Error>
290where
291 T: Serialize<AllocSerializer<N>>,
292{
293 let mut serializer = AllocSerializer::<N>::default();
294 serializer.serialize_value(value)?;
295 Ok(serializer.into_serializer().into_inner())
296}
297
298/// Deserializes a value from the given bytes.
299///
300/// This function is only available with the `alloc` feature because it uses a general-purpose
301/// deserializer. In no-alloc and high-performance environments, the deserializer should be
302/// customized for the specific situation.
303///
304/// # Safety
305///
306/// - The byte slice must represent an archived object
307/// - The root of the object must be stored at the end of the slice (this is the default behavior)
308///
309/// # Examples
310/// ```
311/// let value = vec![1, 2, 3, 4];
312///
313/// let bytes = rkyv::to_bytes::<_, 1024>(&value).expect("failed to serialize vec");
314/// // SAFETY:
315/// // - The byte slice represents an archived object
316/// // - The root of the object is stored at the end of the slice
317/// let deserialized = unsafe {
318/// rkyv::from_bytes_unchecked::<Vec<i32>>(&bytes)
319/// .expect("failed to deserialize vec")
320/// };
321///
322/// assert_eq!(deserialized, value);
323/// ```
324#[cfg(feature = "alloc")]
325#[inline]
326pub unsafe fn from_bytes_unchecked<T>(
327 bytes: &[u8],
328) -> Result<T, <SharedDeserializeMap as Fallible>::Error>
329where
330 T: Archive,
331 T::Archived: Deserialize<T, SharedDeserializeMap>,
332{
333 archived_root::<T>(bytes).deserialize(&mut SharedDeserializeMap::default())
334}