rkyv/impls/core/
ffi.rs

1use core::{
2    alloc::{Layout, LayoutError},
3    ffi::{c_char, CStr},
4    ptr,
5};
6
7use ptr_meta::Pointee;
8use rancor::Fallible;
9
10use crate::{
11    primitive::ArchivedUsize,
12    ser::Writer,
13    traits::{ArchivePointee, LayoutRaw},
14    ArchiveUnsized, ArchivedMetadata, DeserializeUnsized, Portable,
15    SerializeUnsized,
16};
17
18// CStr
19
20impl LayoutRaw for CStr {
21    #[inline]
22    fn layout_raw(
23        metadata: <Self as Pointee>::Metadata,
24    ) -> Result<Layout, LayoutError> {
25        Layout::array::<c_char>(metadata)
26    }
27}
28
29// SAFETY: `CStr` is a byte slice and so has a stable, well-defined layout that
30// is the same on all targets
31unsafe impl Portable for CStr {}
32
33impl ArchiveUnsized for CStr {
34    type Archived = CStr;
35
36    #[inline]
37    fn archived_metadata(&self) -> ArchivedMetadata<Self> {
38        ArchivedUsize::from_native(ptr_meta::metadata(self) as _)
39    }
40}
41
42impl ArchivePointee for CStr {
43    type ArchivedMetadata = ArchivedUsize;
44
45    #[inline]
46    fn pointer_metadata(
47        archived: &Self::ArchivedMetadata,
48    ) -> <Self as Pointee>::Metadata {
49        <[u8]>::pointer_metadata(archived)
50    }
51}
52
53impl<S: Fallible + Writer + ?Sized> SerializeUnsized<S> for CStr {
54    fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
55        let result = serializer.pos();
56        serializer.write(self.to_bytes_with_nul())?;
57        Ok(result)
58    }
59}
60
61impl<D: Fallible + ?Sized> DeserializeUnsized<CStr, D> for CStr {
62    unsafe fn deserialize_unsized(
63        &self,
64        _: &mut D,
65        out: *mut CStr,
66    ) -> Result<(), D::Error> {
67        let slice = self.to_bytes_with_nul();
68        // SAFETY: The caller has guaranteed that `out` is non-null, properly
69        // aligned, valid for writes, and points to memory allocated according
70        // to the layout for the metadata returned from `deserialize_metadata`.
71        // Therefore, `out` points to at least `self.len()` bytes.
72        // `self.as_ptr()` is valid for reads and points to the bytes of `self`
73        // which are also at least `self.len()` bytes. Note here that the length
74        // of the `CStr` contains the null terminator.
75        unsafe {
76            ptr::copy_nonoverlapping(
77                slice.as_ptr(),
78                out.cast::<u8>(),
79                slice.len(),
80            );
81        }
82        Ok(())
83    }
84
85    fn deserialize_metadata(&self) -> <CStr as Pointee>::Metadata {
86        ptr_meta::metadata(self)
87    }
88}