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