use clap_sys::stream::{clap_istream, clap_ostream};
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::os::raw::c_void;
macro_rules! check_null_ptr {
($ret:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
$crate::wrapper::clap::util::check_null_ptr_msg!("Null pointer passed to function", $ret, $ptr $(, $ptrs)*)
};
}
macro_rules! check_null_ptr_msg {
($msg:expr, $ret:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
#[allow(clippy::unused_unit)]
if $ptr.is_null() $(|| $ptrs.is_null())* {
crate::nice_debug_assert_failure!($msg);
return $ret;
}
};
}
macro_rules! clap_call {
{ $obj_ptr:expr=>$function_name:ident($($args:expr),* $(, )?) } => {
match (*$obj_ptr).$function_name {
Some(function_ptr) => function_ptr($($args),*),
None => panic!("'{}::{}' is a null pointer, but this is not allowed", $crate::wrapper::clap::util::type_name_of_ptr($obj_ptr), stringify!($function_name)),
}
}
}
macro_rules! unsafe_clap_call {
{ $($args:tt)* } => {
unsafe { $crate::wrapper::clap::util::clap_call! { $($args)* } }
}
}
#[must_use]
pub fn type_name_of_ptr<T: ?Sized>(_ptr: *const T) -> &'static str {
std::any::type_name::<T>()
}
pub(crate) use check_null_ptr_msg;
pub(crate) use clap_call;
pub struct ClapPtr<T> {
inner: *const T,
}
impl<T> Deref for ClapPtr<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.inner }
}
}
unsafe impl<T> Send for ClapPtr<T> {}
unsafe impl<T> Sync for ClapPtr<T> {}
impl<T> ClapPtr<T> {
pub unsafe fn new(ptr: *const T) -> Self {
Self { inner: ptr }
}
}
pub unsafe trait ByteReadBuffer {
fn len(&self) -> usize;
fn as_mut_ptr(&mut self) -> *mut u8;
}
unsafe impl ByteReadBuffer for &mut [u8] {
fn len(&self) -> usize {
<[u8]>::len(self)
}
fn as_mut_ptr(&mut self) -> *mut u8 {
<[u8]>::as_mut_ptr(self)
}
}
unsafe impl ByteReadBuffer for &mut [MaybeUninit<u8>] {
fn len(&self) -> usize {
<[MaybeUninit<u8>]>::len(self)
}
fn as_mut_ptr(&mut self) -> *mut u8 {
<[MaybeUninit<u8>]>::as_mut_ptr(self) as *mut u8
}
}
pub fn read_stream(stream: &clap_istream, mut slice: impl ByteReadBuffer) -> bool {
let mut read_pos = 0;
while read_pos < slice.len() {
let bytes_read = unsafe_clap_call! {
stream=>read(
stream,
slice.as_mut_ptr().add(read_pos) as *mut c_void,
(slice.len() - read_pos) as u64,
)
};
if bytes_read <= 0 {
return false;
}
read_pos += bytes_read as usize;
}
true
}
pub fn write_stream(stream: &clap_ostream, slice: &[u8]) -> bool {
let mut write_pos = 0;
while write_pos < slice.len() {
let bytes_written = unsafe_clap_call! {
stream=>write(
stream,
slice.as_ptr().add(write_pos) as *const c_void,
(slice.len() - write_pos) as u64,
)
};
if bytes_written <= 0 {
return false;
}
write_pos += bytes_written as usize;
}
true
}