use core::ffi::CStr;
use rancor::{Fallible, ResultExt, Source};
use crate::{
alloc::{
alloc::{alloc, handle_alloc_error},
boxed::Box,
ffi::CString,
},
ffi::{ArchivedCString, CStringResolver},
ser::Writer,
traits::LayoutRaw,
Archive, Deserialize, DeserializeUnsized, Place, Serialize,
};
impl Archive for CString {
type Archived = ArchivedCString;
type Resolver = CStringResolver;
#[inline]
fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>) {
ArchivedCString::resolve_from_c_str(self.as_c_str(), resolver, out);
}
}
impl<S: Fallible + Writer + ?Sized> Serialize<S> for CString {
fn serialize(
&self,
serializer: &mut S,
) -> Result<Self::Resolver, S::Error> {
ArchivedCString::serialize_from_c_str(self.as_c_str(), serializer)
}
}
impl<D> Deserialize<CString, D> for ArchivedCString
where
D: Fallible + ?Sized,
D::Error: Source,
CStr: DeserializeUnsized<CStr, D>,
{
fn deserialize(&self, deserializer: &mut D) -> Result<CString, D::Error> {
let metadata = self.as_c_str().deserialize_metadata();
let layout = <CStr as LayoutRaw>::layout_raw(metadata).into_error()?;
let data_address = if layout.size() > 0 {
let ptr = unsafe { alloc(layout) };
if ptr.is_null() {
handle_alloc_error(layout);
}
ptr
} else {
crate::polyfill::dangling(&layout).as_ptr()
};
let out = ptr_meta::from_raw_parts_mut(data_address.cast(), metadata);
unsafe {
self.as_c_str().deserialize_unsized(deserializer, out)?;
}
let boxed = unsafe { Box::<CStr>::from_raw(out) };
Ok(CString::from(boxed))
}
}
impl PartialEq<CString> for ArchivedCString {
#[inline]
fn eq(&self, other: &CString) -> bool {
PartialEq::eq(self.as_c_str(), other.as_c_str())
}
}
impl PartialEq<ArchivedCString> for CString {
#[inline]
fn eq(&self, other: &ArchivedCString) -> bool {
PartialEq::eq(other.as_c_str(), self.as_c_str())
}
}
#[cfg(test)]
mod tests {
use crate::{
alloc::{ffi::CString, string::String},
api::test::roundtrip,
};
#[test]
fn roundtrip_c_string() {
let value = unsafe {
CString::from_vec_unchecked(
String::from("hello world").into_bytes(),
)
};
roundtrip(&value);
}
}