#[cfg(windows)]
use windows_sys::Win32::Networking::WinSock::WSABUF;
#[allow(clippy::unnecessary_safety_doc)]
pub unsafe trait IoVecBuf: Unpin + 'static {
#[cfg(unix)]
fn read_iovec_ptr(&self) -> *const libc::iovec;
#[cfg(unix)]
fn read_iovec_len(&self) -> usize;
#[cfg(windows)]
fn read_wsabuf_ptr(&self) -> *const WSABUF;
#[cfg(windows)]
fn read_wsabuf_len(&self) -> usize;
}
#[derive(Clone)]
pub struct VecBuf {
#[cfg(unix)]
iovecs: Vec<libc::iovec>,
#[cfg(windows)]
wsabufs: Vec<WSABUF>,
raw: Vec<Vec<u8>>,
}
#[cfg(unix)]
unsafe impl IoVecBuf for VecBuf {
fn read_iovec_ptr(&self) -> *const libc::iovec {
self.iovecs.read_iovec_ptr()
}
fn read_iovec_len(&self) -> usize {
self.iovecs.read_iovec_len()
}
}
#[cfg(unix)]
unsafe impl IoVecBuf for Vec<libc::iovec> {
fn read_iovec_ptr(&self) -> *const libc::iovec {
self.as_ptr()
}
fn read_iovec_len(&self) -> usize {
self.len()
}
}
#[cfg(windows)]
unsafe impl IoVecBuf for VecBuf {
fn read_wsabuf_ptr(&self) -> *const WSABUF {
self.wsabufs.read_wsabuf_ptr()
}
fn read_wsabuf_len(&self) -> usize {
self.wsabufs.read_wsabuf_len()
}
}
#[cfg(windows)]
unsafe impl IoVecBuf for Vec<WSABUF> {
fn read_wsabuf_ptr(&self) -> *const WSABUF {
self.as_ptr()
}
fn read_wsabuf_len(&self) -> usize {
self.len()
}
}
impl From<Vec<Vec<u8>>> for VecBuf {
fn from(vs: Vec<Vec<u8>>) -> Self {
#[cfg(unix)]
{
let iovecs = vs
.iter()
.map(|v| libc::iovec {
iov_base: v.as_ptr() as _,
iov_len: v.len(),
})
.collect();
Self { iovecs, raw: vs }
}
#[cfg(windows)]
{
let wsabufs = vs
.iter()
.map(|v| WSABUF {
buf: v.as_ptr() as _,
len: v.len() as _,
})
.collect();
Self { wsabufs, raw: vs }
}
}
}
impl From<VecBuf> for Vec<Vec<u8>> {
fn from(vb: VecBuf) -> Self {
vb.raw
}
}
#[allow(clippy::unnecessary_safety_doc)]
pub unsafe trait IoVecBufMut: Unpin + 'static {
#[cfg(unix)]
fn write_iovec_ptr(&mut self) -> *mut libc::iovec;
#[cfg(unix)]
fn write_iovec_len(&mut self) -> usize;
#[cfg(windows)]
fn write_wsabuf_ptr(&mut self) -> *mut WSABUF;
#[cfg(windows)]
fn write_wsabuf_len(&mut self) -> usize;
unsafe fn set_init(&mut self, pos: usize);
}
#[cfg(unix)]
unsafe impl IoVecBufMut for VecBuf {
fn write_iovec_ptr(&mut self) -> *mut libc::iovec {
self.read_iovec_ptr() as *mut _
}
fn write_iovec_len(&mut self) -> usize {
self.read_iovec_len()
}
unsafe fn set_init(&mut self, mut len: usize) {
for (idx, iovec) in self.iovecs.iter_mut().enumerate() {
if iovec.iov_len <= len {
self.raw[idx].set_len(iovec.iov_len);
len -= iovec.iov_len;
} else {
if len > 0 {
self.raw[idx].set_len(len);
}
break;
}
}
}
}
#[cfg(windows)]
unsafe impl IoVecBufMut for VecBuf {
fn write_wsabuf_ptr(&mut self) -> *mut WSABUF {
self.read_wsabuf_ptr() as *mut _
}
fn write_wsabuf_len(&mut self) -> usize {
self.read_wsabuf_len()
}
unsafe fn set_init(&mut self, mut len: usize) {
for (idx, wsabuf) in self.wsabufs.iter_mut().enumerate() {
if wsabuf.len as usize <= len {
self.raw[idx].set_len(wsabuf.len as _);
len -= wsabuf.len as usize;
} else {
if len > 0 {
self.raw[idx].set_len(len);
}
break;
}
}
}
}