use std::cell::RefCell;
use std::os::raw::{c_int, c_void};
pub trait PayloadWriter {
fn write_full(&mut self, buf: &mut [u8]) -> bool;
fn write_modified(&mut self, buf: &mut [u8]) -> bool {
self.write_full(buf)
}
fn get_size(&self) -> usize;
}
thread_local! {
pub(crate) static CURRENT_WRITER: RefCell<Option<*mut dyn PayloadWriter>> = RefCell::new(None);
}
pub(crate) unsafe extern "C" fn write_full_cb(buffer: *mut c_void, size: usize) -> c_int {
CURRENT_WRITER.with(|cell| {
if let Some(writer_ptr) = *cell.borrow() {
let writer: &mut dyn PayloadWriter = unsafe { &mut *writer_ptr };
let buf = unsafe { std::slice::from_raw_parts_mut(buffer as *mut u8, size) };
if writer.write_full(buf) { 0 } else { -1 }
} else {
-1
}
})
}
pub(crate) unsafe extern "C" fn write_mod_cb(buffer: *mut c_void, size: usize) -> c_int {
CURRENT_WRITER.with(|cell| {
if let Some(writer_ptr) = *cell.borrow() {
let writer: &mut dyn PayloadWriter = unsafe { &mut *writer_ptr };
let buf = unsafe { std::slice::from_raw_parts_mut(buffer as *mut u8, size) };
if writer.write_modified(buf) { 0 } else { -1 }
} else {
-1
}
})
}
pub(crate) unsafe extern "C" fn get_size_cb() -> usize {
CURRENT_WRITER.with(|cell| {
if let Some(writer_ptr) = *cell.borrow() {
let writer: &mut dyn PayloadWriter = unsafe { &mut *writer_ptr };
writer.get_size()
} else {
0
}
})
}