use std::os::raw::c_char;
use std::borrow::Cow;
use std::ffi;
use std::ptr::null;
use std::io;
pub unsafe fn from_cstr(s: *const c_char) -> io::Result<&'static str> {
ffi::CStr::from_ptr(s)
.to_str()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
}
#[derive(Clone,Debug)]
pub struct CStr<'a>(Cow<'a, ffi::CStr>);
impl<'a> CStr<'a> {
pub fn from<T>(s: &'a T) -> Result<Self, ffi::NulError>
where Self: CStrFrom<'a, T>
{
CStrFrom::cstr_from(s)
}
pub fn as_ptr(&self) -> *const c_char {
self.0.as_ptr()
}
}
#[derive(Clone,Debug)]
pub struct NullableCStr<'a>(Option<Cow<'a, ffi::CStr>>);
impl<'a> NullableCStr<'a> {
pub fn from<T>(s: &'a T) -> Result<Self, ffi::NulError>
where Self: CStrFrom<'a, T>
{
CStrFrom::cstr_from(s)
}
pub fn as_ptr(&self) -> *const c_char {
match self.0 {
Some(ref s) => s.as_ptr(),
None => null()
}
}
}
pub trait CStrFrom<'a, T>: Sized {
fn cstr_from(_: &'a T) -> Result<Self, ffi::NulError>;
}
impl<'a, T: AsRef<str>> CStrFrom<'a, T> for CStr<'a> {
fn cstr_from(s: &'a T) -> Result<Self, ffi::NulError> {
Ok(CStr(Cow::Owned(ffi::CString::new(s.as_ref())?)))
}
}
impl<'a, T: AsRef<str>> CStrFrom<'a, Option<T>> for NullableCStr<'a> {
fn cstr_from(s: &'a Option<T>) -> Result<Self, ffi::NulError> {
match *s {
Some(ref s) => Ok(NullableCStr(Some(
Cow::Owned(ffi::CString::new(s.as_ref())?)
))),
None => Ok(NullableCStr(None)),
}
}
}