use crate::ffi_fn;
use libc::c_char;
use std::ffi::{CStr, CString};
use std::ops::Not;
pub(crate) fn to_c(t: &str) -> anyhow::Result<*mut c_char> {
Ok(CString::new(t)?.into_raw())
}
ffi_fn! {
fn pactffi_string_delete(string: *mut c_char) {
if string.is_null().not() {
let string = unsafe { CString::from_raw(string) };
std::mem::drop(string);
}
}
}
#[macro_export]
macro_rules! cstr {
( $name:ident ) => {{
use ::std::ffi::CStr;
if $name.is_null() {
::anyhow::bail!(concat!(stringify!($name), " is null"));
}
unsafe { CStr::from_ptr($name) }
}};
}
#[macro_export]
macro_rules! safe_str {
( $name:ident ) => {{
use ::anyhow::Context;
$crate::cstr!($name).to_str().context(concat!(
"error parsing ",
stringify!($name),
" as UTF-8"
))?
}};
}
pub(crate) fn if_null(s: *const c_char, default: &str) -> String {
optional_str(s).unwrap_or_else(|| default.to_string())
}
pub(crate) fn optional_str(s: *const c_char) -> Option<String> {
if s.is_null() {
None
} else {
let value = unsafe { CStr::from_ptr(s).to_string_lossy().to_string() };
if value.is_empty() {
None
} else {
Some(value)
}
}
}