use std::ffi::c_char;
use std::ptr::NonNull;
use std::time::Duration;
#[cfg(unix)]
use std::os::fd::RawFd;
use crate::api::resource::Resource;
#[derive(Clone, Copy)]
pub struct RawBuf {
pub ptr: *mut u8,
pub len: usize,
}
unsafe impl Send for RawBuf {}
unsafe impl Sync for RawBuf {}
pub struct OpBuf {
ptr: Option<NonNull<()>>,
drop_fn: unsafe fn(*mut ()),
}
impl OpBuf {
pub fn new<T: Send + 'static>(value: T) -> Self {
let boxed = Box::new(value);
Self {
ptr: Some(NonNull::new(Box::into_raw(boxed).cast()).unwrap()),
drop_fn: Self::drop_erased::<T>,
}
}
unsafe fn drop_erased<T>(ptr: *mut ()) {
drop(unsafe { Box::from_raw(ptr as *mut T) });
}
pub unsafe fn peek<T: Copy>(&self) -> T {
let ptr = self
.ptr
.as_ref()
.expect("ErasedBuffer already taken")
.as_ptr()
.cast::<T>();
unsafe { *ptr }
}
pub unsafe fn take<T>(mut self) -> T {
let ptr = self.ptr.take().unwrap().as_ptr().cast();
*unsafe { Box::from_raw(ptr) }
}
}
impl Drop for OpBuf {
fn drop(&mut self) {
if let Some(ptr) = self.ptr.take() {
unsafe { (self.drop_fn)(ptr.as_ptr()) }
};
}
}
unsafe impl Send for OpBuf {}
unsafe impl Sync for OpBuf {}
pub enum Op {
Read {
fd: Resource,
buffer: OpBuf,
},
Write {
fd: Resource,
buffer: OpBuf,
},
ReadAt {
fd: Resource,
offset: i64,
buffer: OpBuf,
},
WriteAt {
fd: Resource,
offset: i64,
buffer: OpBuf,
},
Send {
fd: Resource,
flags: i32,
buffer: OpBuf,
},
Recv {
fd: Resource,
flags: i32,
buffer: OpBuf,
},
Accept {
fd: Resource,
addr: *mut libc::sockaddr_storage,
len: *mut libc::socklen_t,
},
Connect {
fd: Resource,
addr: *const libc::sockaddr_storage,
len: libc::socklen_t,
connect_called: bool,
},
Bind {
fd: Resource,
addr: *const libc::sockaddr_storage,
addrlen: libc::socklen_t,
},
Listen {
fd: Resource,
backlog: i32,
},
Shutdown {
fd: Resource,
how: i32,
},
Socket {
domain: i32,
ty: i32,
proto: i32,
},
OpenAt {
dir_fd: Resource,
path: *const c_char,
flags: i32,
},
Close {
#[cfg(unix)]
fd: RawFd,
#[cfg(windows)]
handle: std::os::windows::io::RawHandle,
#[cfg(windows)]
is_socket: bool,
},
Fsync {
fd: Resource,
},
Truncate {
fd: Resource,
size: u64,
},
LinkAt {
old_dir_fd: Resource,
old_path: *const c_char,
new_dir_fd: Resource,
new_path: *const c_char,
},
SymlinkAt {
dir_fd: Resource,
target: *const c_char,
linkpath: *const c_char,
},
#[cfg(target_os = "linux")]
Tee {
fd_in: Resource,
fd_out: Resource,
size: u32,
},
Timeout {
duration: Duration,
#[cfg(target_os = "linux")]
timer_fd: Resource,
#[cfg(target_os = "linux")]
timespec: *const libc::timespec,
},
Nop,
}
unsafe impl Send for Op {}
unsafe impl Sync for Op {}