compio_buf/io_slice.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
use std::mem::MaybeUninit;
#[cfg(unix)]
mod sys {
use std::mem::MaybeUninit;
#[repr(transparent)]
pub struct Inner(libc::iovec);
impl Inner {
pub fn new(ptr: *mut MaybeUninit<u8>, len: usize) -> Self {
Self(libc::iovec {
iov_base: ptr as *mut libc::c_void,
iov_len: len,
})
}
pub fn len(&self) -> usize {
self.0.iov_len
}
pub fn as_ptr(&self) -> *mut MaybeUninit<u8> {
self.0.iov_base as *mut MaybeUninit<u8>
}
}
}
#[cfg(windows)]
mod sys {
use std::mem::MaybeUninit;
// Copied from std
#[repr(C)]
#[allow(clippy::upper_case_acronyms)]
struct WSABUF {
pub len: u32,
pub buf: *mut MaybeUninit<u8>,
}
#[repr(transparent)]
pub struct Inner(WSABUF);
impl Inner {
pub fn new(ptr: *mut MaybeUninit<u8>, len: usize) -> Self {
Self(WSABUF {
len: len as u32,
buf: ptr,
})
}
pub fn len(&self) -> usize {
self.0.len as _
}
pub fn as_ptr(&self) -> *mut MaybeUninit<u8> {
self.0.buf
}
}
}
#[cfg(not(any(unix, windows)))]
compile_error!("`IoSlice` only available on unix and windows");
/// An unsafe, `'static`, initialized, and immutable slice of bytes to interact
/// with system API.
///
/// Like [`IoSlice`] in `std`, `IoSlice` guarantees the ABI compatibility
/// on unix and windows, but without the lifetime, makes it easier to use with
/// compio driver at the cost of unsafe to construct. `IoSlice` should only be
/// used with compio driver.
///
/// [`IoSlice`]: std::io::IoSlice
#[repr(transparent)]
pub struct IoSlice(sys::Inner);
impl IoSlice {
/// Create a new `IoSlice` from a raw pointer and a length.
///
/// # Safety
/// The caller must ensure that:
/// - the pointer is valid for the lifetime of the `IoSlice`
/// - the length is correct
/// - the content of the buffer is initialized
/// - the pointer is not used for mutating while the `IoSlice` is in use
pub unsafe fn new(ptr: *const u8, len: usize) -> Self {
Self(sys::Inner::new(ptr as _, len))
}
/// Create a new `IoSlice` from an initialized slice.
///
/// # Safety
/// The caller must ensure that, during the lifetime of the `IoSlice`, the
/// slice is valid the and is not used for mutating.
pub unsafe fn from_slice(slice: &[u8]) -> Self {
Self::new(slice.as_ptr() as _, slice.len())
}
/// Get the pointer to the buffer.
pub fn as_ptr(&self) -> *const u8 {
self.0.as_ptr() as _
}
/// Get the length of the buffer.
pub fn len(&self) -> usize {
self.0.len()
}
/// Check if the buffer is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
/// An unsafe, `'static`, maybe uninitialized, and mutable slice of bytes to
/// interact with system API.
///
/// Like [`IoSliceMut`] in `std`, `IoSliceMut` guarantees the ABI compatibility
/// on unix and windows, but without the lifetime and accepts
/// [`MaybeUninit<u8>`], makes it easier to use with compio driver at the cost
/// of unsafe to construct. `IoSliceMut` should only be used with compio driver.
///
/// [`IoSliceMut`]: std::io::IoSliceMut
#[repr(transparent)]
pub struct IoSliceMut(sys::Inner);
impl IoSliceMut {
/// Create a new `IoSliceMut` from a raw pointer and a length.
///
/// # Safety
/// The caller must ensure that:
/// - the pointer is valid for the lifetime of the `IoSliceMut`
/// - the length is correct (the content can be uninitialized, but must be
/// accessible)
/// - the pointer is not used for anything else while the `IoSliceMut` is in
/// use
pub unsafe fn new(ptr: *mut MaybeUninit<u8>, len: usize) -> Self {
Self(sys::Inner::new(ptr, len))
}
/// Create a new `IoSliceMut` from an initialized slice.
///
/// # Safety
/// The caller must ensure that, during the lifetime of the `IoSliceMut`,
/// the slice is valid the and is not used for anything else.
pub unsafe fn from_slice(slice: &mut [u8]) -> Self {
Self::new(slice.as_mut_ptr() as _, slice.len())
}
/// Create a new `IoSliceMut` from a uninitialized slice.
///
/// # Safety
/// The caller must ensure that, during the lifetime of the `IoSliceMut`,
/// the slice is valid the and is not used for anything else.
pub unsafe fn from_uninit(slice: &mut [MaybeUninit<u8>]) -> Self {
Self::new(slice.as_mut_ptr(), slice.len())
}
/// Get the pointer to the buffer.
pub fn as_ptr(&self) -> *mut MaybeUninit<u8> {
self.0.as_ptr()
}
/// Get the length of the buffer.
pub fn len(&self) -> usize {
self.0.len()
}
/// Check if the buffer is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}