use libc::c_void;
use self::ffi::{rust_write, rust_writter_drop, go::ffi_rust_IO_writter_new, rust_io_writter_drop};
mod ffi {
use std::{ffi::c_uint, ptr::null, mem};
use libc::c_void;
use crate::util::util::ffi::Error;
use self::go::ffi_rust_IO_writter_drop;
use super::{GoIOWriterImpl, GoIOWritterPtr, GoIOWritter};
pub type GoIOWrapperPtr = extern "C" fn (*const c_void, *const c_void, c_uint) -> ExecRustWriteResult;
pub type GoIOWritterDropPtr = extern "C" fn(*const c_void);
#[repr(C)]
pub struct ExecRustWriteResult {
len: c_uint,
err: Error,
}
pub extern "C" fn rust_writter_drop (me: GoIOWritterPtr) {
let rustlogger = unsafe { Box::from_raw(me as *mut GoIOWriterImpl) };
drop(rustlogger); }
pub extern "C" fn rust_write(rust_writter: GoIOWritterPtr, buff: *const c_void, len: c_uint) -> ExecRustWriteResult {
let mut rustlogger = unsafe { Box::from_raw(rust_writter as *mut GoIOWriterImpl) };
let data_slice = unsafe { std::slice::from_raw_parts(buff as *const u8, len as usize) };
let result = match rustlogger.rust_writter.write(data_slice) {
Ok(len) => ExecRustWriteResult {
len: len as c_uint,
err: null(),
},
Err(err) => {
let err = match std::ffi::CString::new(err.to_string()) {
Ok(v) => v.as_ptr(),
Err(e) => {
println!("rust write err defer null error: {e}");
null()
}
};
ExecRustWriteResult {
len: 0, err: err
}
}
};
mem::forget(rustlogger);
result
}
pub mod go {
use crate::util::go_iowritter::GoIOWritterPtr;
use super::{GoIOWrapperPtr, GoIOWritterDropPtr};
extern "C" {
pub fn ffi_rust_IO_writter_new(wrapperPtr: GoIOWrapperPtr, writterPtr: GoIOWritterPtr, dropFuncPtr: GoIOWritterDropPtr) -> GoIOWritterPtr;
pub fn ffi_rust_IO_writter_drop(writterPtr: GoIOWritterPtr);
}
}
pub(crate) fn rust_io_writter_drop (writter: &mut GoIOWritter) {
unsafe { ffi_rust_IO_writter_drop(writter.go_io_writter_ptr) };
}
}
pub(crate) type GoIOWritterPtr = *const c_void;
struct GoIOWriterImpl {
rust_writter: Box<dyn std::io::Write>,
}
impl GoIOWriterImpl {
pub fn new <T: std::io::Write + 'static>(writter: T) -> *const c_void {
let me = Box::new(Self {
rust_writter: Box::new(writter)
});
let myptr = Box::into_raw(me) as *const c_void;
let result = unsafe { ffi_rust_IO_writter_new(rust_write, myptr, rust_writter_drop) };
if result.is_null() {
panic!("go: ffi_rust_IO_writter_new error");
}
result
}
}
pub struct GoIOWritter {
pub(crate) go_io_writter_ptr: GoIOWritterPtr,
}
impl GoIOWritter {
pub fn new <T: std::io::Write + 'static>(writter: T) -> Self {
Self {
go_io_writter_ptr: GoIOWriterImpl::new(writter),
}
}
}
impl Drop for GoIOWritter {
fn drop(&mut self) {
rust_io_writter_drop(self);
}
}