rkyv_test/impls/std/
ffi.rs

1use crate::{
2    ffi::{ArchivedCString, CStringResolver},
3    ser::Serializer,
4    Archive, ArchivePointee, ArchiveUnsized, Archived, ArchivedMetadata, Deserialize,
5    DeserializeUnsized, Fallible, FixedUsize, Serialize, SerializeUnsized,
6};
7use core::{alloc::Layout, ptr};
8use ptr_meta::Pointee;
9use std::alloc;
10use std::ffi::{CStr, CString};
11
12// CStr
13
14impl ArchiveUnsized for CStr {
15    type Archived = CStr;
16
17    type MetadataResolver = ();
18
19    #[inline]
20    unsafe fn resolve_metadata(
21        &self,
22        _: usize,
23        _: Self::MetadataResolver,
24        out: *mut ArchivedMetadata<Self>,
25    ) {
26        out.write(to_archived!(ptr_meta::metadata(self) as FixedUsize))
27    }
28}
29
30impl ArchivePointee for CStr {
31    type ArchivedMetadata = Archived<usize>;
32
33    #[inline]
34    fn pointer_metadata(archived: &Self::ArchivedMetadata) -> <Self as Pointee>::Metadata {
35        <[u8]>::pointer_metadata(archived)
36    }
37}
38
39impl<S: Serializer + ?Sized> SerializeUnsized<S> for CStr {
40    #[inline]
41    fn serialize_unsized(&self, serializer: &mut S) -> Result<usize, S::Error> {
42        let result = serializer.pos();
43        serializer.write(self.to_bytes_with_nul())?;
44        Ok(result)
45    }
46
47    #[inline]
48    fn serialize_metadata(&self, _: &mut S) -> Result<Self::MetadataResolver, S::Error> {
49        Ok(())
50    }
51}
52
53impl<D: Fallible + ?Sized> DeserializeUnsized<CStr, D> for <CStr as ArchiveUnsized>::Archived {
54    #[inline]
55    unsafe fn deserialize_unsized(
56        &self,
57        _: &mut D,
58        mut alloc: impl FnMut(Layout) -> *mut u8,
59    ) -> Result<*mut (), D::Error> {
60        let slice = self.to_bytes_with_nul();
61        let bytes = alloc(Layout::array::<u8>(slice.len()).unwrap());
62        assert!(!bytes.is_null());
63        ptr::copy_nonoverlapping(slice.as_ptr(), bytes, slice.len());
64        Ok(bytes.cast())
65    }
66
67    #[inline]
68    fn deserialize_metadata(&self, _: &mut D) -> Result<<CStr as Pointee>::Metadata, D::Error> {
69        Ok(ptr_meta::metadata(self))
70    }
71}
72
73// CString
74
75impl PartialEq<CString> for ArchivedCString {
76    #[inline]
77    fn eq(&self, other: &CString) -> bool {
78        PartialEq::eq(self.as_c_str(), other.as_c_str())
79    }
80}
81
82impl PartialEq<ArchivedCString> for CString {
83    #[inline]
84    fn eq(&self, other: &ArchivedCString) -> bool {
85        PartialEq::eq(other.as_c_str(), self.as_c_str())
86    }
87}
88
89impl Archive for CString {
90    type Archived = ArchivedCString;
91    type Resolver = CStringResolver;
92
93    #[inline]
94    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
95        ArchivedCString::resolve_from_c_str(self.as_c_str(), pos, resolver, out);
96    }
97}
98
99impl<S: Serializer + ?Sized> Serialize<S> for CString {
100    #[inline]
101    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
102        ArchivedCString::serialize_from_c_str(self.as_c_str(), serializer)
103    }
104}
105
106impl<D: Fallible + ?Sized> Deserialize<CString, D> for Archived<CString>
107where
108    CStr: DeserializeUnsized<CStr, D>,
109{
110    #[inline]
111    fn deserialize(&self, deserializer: &mut D) -> Result<CString, D::Error> {
112        unsafe {
113            let data_address = self
114                .as_c_str()
115                .deserialize_unsized(deserializer, |layout| alloc::alloc(layout))?;
116            let metadata = self.as_c_str().deserialize_metadata(deserializer)?;
117            let ptr = ptr_meta::from_raw_parts_mut(data_address, metadata);
118            Ok(Box::<CStr>::from_raw(ptr).into())
119        }
120    }
121}