#[cfg(feature = "alloc")]
mod aligned_vec;
mod scratch_vec;
#[cfg(feature = "alloc")]
use crate::{
de::deserializers::SharedDeserializeMap,
ser::{serializers::AllocSerializer, Serializer},
Deserialize, Fallible, Serialize,
};
use crate::{Archive, ArchiveUnsized, RelPtr};
use core::{
mem,
ops::{Deref, DerefMut},
pin::Pin,
};
#[doc(inline)]
#[cfg(feature = "alloc")]
pub use self::aligned_vec::*;
#[doc(inline)]
pub use self::scratch_vec::*;
#[cfg(debug_assertions)]
#[inline]
fn check_alignment<T>(ptr: *const u8) {
let expect_align = core::mem::align_of::<T>();
let actual_align = (ptr as usize) & (expect_align - 1);
debug_assert_eq!(
actual_align,
0,
concat!(
"unaligned buffer, expected alignment {} but found alignment {}\n",
"help: rkyv requires byte buffers to be aligned to access the data inside.\n",
" Using an ALignedVec or manually aligning your data with #[align(...)]\n",
" may resolve this issue.",
),
expect_align,
1 << actual_align.trailing_zeros()
);
}
#[inline]
pub unsafe fn archived_value<T: Archive + ?Sized>(bytes: &[u8], pos: usize) -> &T::Archived {
#[cfg(debug_assertions)]
check_alignment::<T::Archived>(bytes.as_ptr());
&*bytes.as_ptr().add(pos).cast()
}
#[inline]
pub unsafe fn archived_value_mut<T: Archive + ?Sized>(
bytes: Pin<&mut [u8]>,
pos: usize,
) -> Pin<&mut T::Archived> {
#[cfg(debug_assertions)]
check_alignment::<T::Archived>(bytes.as_ptr());
Pin::new_unchecked(&mut *bytes.get_unchecked_mut().as_mut_ptr().add(pos).cast())
}
#[inline]
pub unsafe fn archived_unsized_value<T: ArchiveUnsized + ?Sized>(
bytes: &[u8],
pos: usize,
) -> &T::Archived {
#[cfg(debug_assertions)]
check_alignment::<RelPtr<T::Archived>>(bytes.as_ptr());
let rel_ptr = &*bytes.as_ptr().add(pos).cast::<RelPtr<T::Archived>>();
&*rel_ptr.as_ptr()
}
#[inline]
pub unsafe fn archived_unsized_value_mut<T: ArchiveUnsized + ?Sized>(
bytes: Pin<&mut [u8]>,
pos: usize,
) -> Pin<&mut T::Archived> {
#[cfg(debug_assertions)]
check_alignment::<RelPtr<T::Archived>>(bytes.as_ptr());
let rel_ptr = &mut *bytes
.get_unchecked_mut()
.as_mut_ptr()
.add(pos)
.cast::<RelPtr<T::Archived>>();
Pin::new_unchecked(&mut *rel_ptr.as_mut_ptr())
}
#[inline]
pub unsafe fn archived_root<T: Archive + ?Sized>(bytes: &[u8]) -> &T::Archived {
archived_value::<T>(bytes, bytes.len() - mem::size_of::<T::Archived>())
}
#[inline]
pub unsafe fn archived_root_mut<T: Archive + ?Sized>(
bytes: Pin<&mut [u8]>,
) -> Pin<&mut T::Archived> {
let pos = bytes.len() - mem::size_of::<T::Archived>();
archived_value_mut::<T>(bytes, pos)
}
#[inline]
pub unsafe fn archived_unsized_root<T: ArchiveUnsized + ?Sized>(bytes: &[u8]) -> &T::Archived {
archived_unsized_value::<T>(bytes, bytes.len() - mem::size_of::<RelPtr<T::Archived>>())
}
#[inline]
pub unsafe fn archived_unsized_root_mut<T: ArchiveUnsized + ?Sized>(
bytes: Pin<&mut [u8]>,
) -> Pin<&mut T::Archived> {
let pos = bytes.len() - mem::size_of::<RelPtr<T::Archived>>();
archived_unsized_value_mut::<T>(bytes, pos)
}
#[derive(Clone, Copy, Debug)]
#[repr(C, align(16))]
pub struct AlignedBytes<const N: usize>(pub [u8; N]);
impl<const N: usize> Default for AlignedBytes<N> {
fn default() -> Self {
Self([0; N])
}
}
impl<const N: usize> Deref for AlignedBytes<N> {
type Target = [u8; N];
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const N: usize> DerefMut for AlignedBytes<N> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<const N: usize> AsRef<[u8]> for AlignedBytes<N> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<const N: usize> AsMut<[u8]> for AlignedBytes<N> {
#[inline]
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}
#[cfg(feature = "alloc")]
#[inline]
pub fn to_bytes<T, const N: usize>(
value: &T,
) -> Result<AlignedVec, <AllocSerializer<N> as Fallible>::Error>
where
T: Serialize<AllocSerializer<N>>,
{
let mut serializer = AllocSerializer::<N>::default();
serializer.serialize_value(value)?;
Ok(serializer.into_serializer().into_inner())
}
#[cfg(feature = "alloc")]
#[inline]
pub unsafe fn from_bytes_unchecked<T>(
bytes: &[u8],
) -> Result<T, <SharedDeserializeMap as Fallible>::Error>
where
T: Archive,
T::Archived: Deserialize<T, SharedDeserializeMap>,
{
archived_root::<T>(bytes).deserialize(&mut SharedDeserializeMap::default())
}