pub(crate) use capsule_ffi::*;
use crate::warn;
use anyhow::Result;
use std::error::Error;
use std::ffi::{CStr, CString};
use std::os::raw;
use std::ptr::NonNull;
pub(crate) trait AsStr {
fn as_str(&self) -> &str;
}
impl AsStr for *const raw::c_char {
#[inline]
fn as_str(&self) -> &str {
unsafe {
CStr::from_ptr(*self).to_str().unwrap_or_else(|_| {
warn!("invalid UTF8 data");
Default::default()
})
}
}
}
impl AsStr for [raw::c_char] {
#[inline]
fn as_str(&self) -> &str {
unsafe {
CStr::from_ptr(self.as_ptr()).to_str().unwrap_or_else(|_| {
warn!("invalid UTF8 data");
Default::default()
})
}
}
}
pub(crate) trait ToCString {
fn into_cstring(self) -> CString;
}
impl ToCString for String {
#[inline]
fn into_cstring(self) -> CString {
CString::new(self).unwrap()
}
}
impl ToCString for &str {
#[inline]
fn into_cstring(self) -> CString {
CString::new(self).unwrap()
}
}
pub(crate) trait ToResult {
type Ok;
fn into_result<E, F>(self, f: F) -> Result<Self::Ok>
where
E: Error + Send + Sync + 'static,
F: FnOnce(Self) -> E,
Self: Sized;
}
impl<T> ToResult for *mut T {
type Ok = NonNull<T>;
#[inline]
fn into_result<E, F>(self, f: F) -> Result<Self::Ok>
where
E: Error + Send + Sync + 'static,
F: FnOnce(Self) -> E,
{
NonNull::new(self).ok_or_else(|| f(self).into())
}
}
impl<T> ToResult for *const T {
type Ok = *const T;
#[inline]
fn into_result<E, F>(self, f: F) -> Result<Self::Ok>
where
E: Error + Send + Sync + 'static,
F: FnOnce(Self) -> E,
{
if self.is_null() {
Err(f(self).into())
} else {
Ok(self)
}
}
}
impl ToResult for raw::c_int {
type Ok = u32;
#[inline]
fn into_result<E, F>(self, f: F) -> Result<Self::Ok>
where
E: Error + Send + Sync + 'static,
F: FnOnce(Self) -> E,
{
if self >= 0 {
Ok(self as u32)
} else {
Err(f(self).into())
}
}
}