1use core::ffi::CStr;
2
3use rancor::{Fallible, ResultExt, Source};
4
5use crate::{
6 alloc::{alloc::alloc, boxed::Box, ffi::CString},
7 ffi::{ArchivedCString, CStringResolver},
8 ser::Writer,
9 traits::LayoutRaw,
10 Archive, Deserialize, DeserializeUnsized, Place, Serialize,
11};
12
13impl Archive for CString {
16 type Archived = ArchivedCString;
17 type Resolver = CStringResolver;
18
19 #[inline]
20 fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
21 ArchivedCString::resolve_from_c_str(self.as_c_str(), resolver, out);
22 }
23}
24
25impl<S: Fallible + Writer + ?Sized> Serialize<S> for CString {
26 fn serialize(
27 &self,
28 serializer: &mut S,
29 ) -> Result<Self::Resolver, S::Error> {
30 ArchivedCString::serialize_from_c_str(self.as_c_str(), serializer)
31 }
32}
33
34impl<D> Deserialize<CString, D> for ArchivedCString
35where
36 D: Fallible + ?Sized,
37 D::Error: Source,
38 CStr: DeserializeUnsized<CStr, D>,
39{
40 fn deserialize(&self, deserializer: &mut D) -> Result<CString, D::Error> {
41 let metadata = self.as_c_str().deserialize_metadata();
42 let layout = <CStr as LayoutRaw>::layout_raw(metadata).into_error()?;
43 let data_address = if layout.size() > 0 {
44 unsafe { alloc(layout) }
45 } else {
46 crate::polyfill::dangling(&layout).as_ptr()
47 };
48 let out = ptr_meta::from_raw_parts_mut(data_address.cast(), metadata);
49 unsafe {
50 self.as_c_str().deserialize_unsized(deserializer, out)?;
51 }
52 let boxed = unsafe { Box::<CStr>::from_raw(out) };
53 Ok(CString::from(boxed))
54 }
55}
56
57impl PartialEq<CString> for ArchivedCString {
58 #[inline]
59 fn eq(&self, other: &CString) -> bool {
60 PartialEq::eq(self.as_c_str(), other.as_c_str())
61 }
62}
63
64impl PartialEq<ArchivedCString> for CString {
65 #[inline]
66 fn eq(&self, other: &ArchivedCString) -> bool {
67 PartialEq::eq(other.as_c_str(), self.as_c_str())
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use crate::{
74 alloc::{ffi::CString, string::String},
75 api::test::roundtrip,
76 };
77
78 #[test]
79 fn roundtrip_c_string() {
80 let value = unsafe {
81 CString::from_vec_unchecked(
82 String::from("hello world").into_bytes(),
83 )
84 };
85 roundtrip(&value);
86 }
87}