async-dnssd 0.2.0

Asynchronous wrapper for DNS-SD C libraries
Documentation
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)),
		}
	}
}