impls for null-terminated FFI string types

Fixes #800.
This commit is contained in:
Jon Gjengset 2017-03-03 16:09:37 -05:00
parent d70636f4d4
commit 857974ab8a
No known key found for this signature in database
GPG Key ID: D64AC9D67176DC71
2 changed files with 53 additions and 0 deletions

View File

@ -25,6 +25,8 @@ use std::net;
#[cfg(feature = "std")]
use std::path;
use core::str;
#[cfg(feature = "std")]
use std::ffi::{CStr, CString};
#[cfg(feature = "std")]
use std::rc::Rc;
@ -295,6 +297,33 @@ impl Deserialize for String {
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Deserialize for Box<CStr> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer
{
use std::mem;
let s = try!(CString::deserialize(deserializer));
let slice = s.into_bytes_with_nul().into_boxed_slice();
Ok(unsafe { mem::transmute::<Box<[u8]>, Box<CStr>>(slice) })
}
}
#[cfg(feature = "std")]
impl Deserialize for CString {
fn deserialize<D>(deserializer: D) -> Result<CString, D::Error>
where D: Deserializer
{
let mut v: Vec<u8> = try!(Deserialize::deserialize(deserializer));
v.pop(); // cut trailing NULL, because CString::new adds it
CString::new(v)
.map_err(|e| Error::custom(format!("unexpected NULL at byte {}", e.nul_position())))
}
}
///////////////////////////////////////////////////////////////////////////////
struct OptionVisitor<T> {
marker: PhantomData<T>,
}

View File

@ -22,6 +22,8 @@ use core::ops;
#[cfg(feature = "std")]
use std::path;
#[cfg(feature = "std")]
use std::ffi::{CString, CStr};
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::rc::Rc;
@ -98,6 +100,28 @@ impl Serialize for String {
///////////////////////////////////////////////////////////////////////////////
#[cfg(feature = "std")]
impl Serialize for CStr {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(self.to_bytes_with_nul()).serialize(serializer)
}
}
#[cfg(feature = "std")]
impl Serialize for CString {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(self.to_bytes_with_nul()).serialize(serializer)
}
}
///////////////////////////////////////////////////////////////////////////////
impl<T> Serialize for Option<T>
where T: Serialize
{