monoio/buf/io_vec_buf.rs
1// use super::shared_buf::Shared;
2
3#[cfg(windows)]
4use windows_sys::Win32::Networking::WinSock::WSABUF;
5
6/// An `io_uring` compatible iovec buffer.
7///
8/// # Safety
9/// See the safety note of the methods.
10#[allow(clippy::unnecessary_safety_doc)]
11pub unsafe trait IoVecBuf: Unpin + 'static {
12 /// Returns a raw pointer to iovec struct.
13 /// struct iovec {
14 /// void *iov_base; /* Starting address */
15 /// size_t iov_len; /* Number of bytes to transfer */
16 /// };
17 /// \[iovec1\]\[iovec2\]\[iovec3\]...
18 /// ^ The pointer
19 ///
20 /// # Safety
21 /// The implementation must ensure that, while the runtime owns the value,
22 /// the pointer returned by `stable_mut_ptr` **does not** change.
23 /// Also, the value pointed must be a valid iovec struct.
24 #[cfg(unix)]
25 fn read_iovec_ptr(&self) -> *const libc::iovec;
26
27 /// Returns the count of iovec struct behind the pointer.
28 ///
29 /// # Safety
30 /// There must be really that number of iovec here.
31 #[cfg(unix)]
32 fn read_iovec_len(&self) -> usize;
33
34 /// Returns a raw pointer to WSABUF struct.
35 #[cfg(windows)]
36 fn read_wsabuf_ptr(&self) -> *const WSABUF;
37
38 /// Returns the count of WSABUF struct behind the pointer.
39 #[cfg(windows)]
40 fn read_wsabuf_len(&self) -> usize;
41}
42
43/// A intermediate struct that impl IoVecBuf and IoVecBufMut.
44#[derive(Clone)]
45pub struct VecBuf {
46 #[cfg(unix)]
47 iovecs: Vec<libc::iovec>,
48 #[cfg(windows)]
49 wsabufs: Vec<WSABUF>,
50 raw: Vec<Vec<u8>>,
51}
52
53#[cfg(unix)]
54unsafe impl IoVecBuf for VecBuf {
55 fn read_iovec_ptr(&self) -> *const libc::iovec {
56 self.iovecs.read_iovec_ptr()
57 }
58 fn read_iovec_len(&self) -> usize {
59 self.iovecs.read_iovec_len()
60 }
61}
62
63#[cfg(unix)]
64unsafe impl IoVecBuf for Vec<libc::iovec> {
65 fn read_iovec_ptr(&self) -> *const libc::iovec {
66 self.as_ptr()
67 }
68
69 fn read_iovec_len(&self) -> usize {
70 self.len()
71 }
72}
73
74#[cfg(windows)]
75unsafe impl IoVecBuf for VecBuf {
76 fn read_wsabuf_ptr(&self) -> *const WSABUF {
77 self.wsabufs.read_wsabuf_ptr()
78 }
79 fn read_wsabuf_len(&self) -> usize {
80 self.wsabufs.read_wsabuf_len()
81 }
82}
83
84#[cfg(windows)]
85unsafe impl IoVecBuf for Vec<WSABUF> {
86 fn read_wsabuf_ptr(&self) -> *const WSABUF {
87 self.as_ptr()
88 }
89
90 fn read_wsabuf_len(&self) -> usize {
91 self.len()
92 }
93}
94
95impl From<Vec<Vec<u8>>> for VecBuf {
96 fn from(vs: Vec<Vec<u8>>) -> Self {
97 #[cfg(unix)]
98 {
99 let iovecs = vs
100 .iter()
101 .map(|v| libc::iovec {
102 iov_base: v.as_ptr() as _,
103 iov_len: v.len(),
104 })
105 .collect();
106 Self { iovecs, raw: vs }
107 }
108 #[cfg(windows)]
109 {
110 let wsabufs = vs
111 .iter()
112 .map(|v| WSABUF {
113 buf: v.as_ptr() as _,
114 len: v.len() as _,
115 })
116 .collect();
117 Self { wsabufs, raw: vs }
118 }
119 }
120}
121
122impl From<VecBuf> for Vec<Vec<u8>> {
123 fn from(vb: VecBuf) -> Self {
124 vb.raw
125 }
126}
127
128// /// SliceVec impl IoVecBuf and IoVecBufMut.
129// pub struct SliceVec<T> {
130// iovecs: Vec<libc::iovec>,
131// indices: Vec<(usize, usize)>,
132// buf: T,
133// }
134
135// impl<T> SliceVec<T> {
136// /// New SliceVec.
137// pub fn new(buf: T) -> Self {
138// Self {
139// iovecs: Default::default(),
140// indices: Default::default(),
141// buf,
142// }
143// }
144
145// /// New SliceVec with given indices.
146// pub fn new_with_indices(buf: T, indices: Vec<(usize, usize)>) -> Self {
147// Self {
148// iovecs: Default::default(),
149// indices,
150// buf,
151// }
152// }
153// }
154
155// unsafe impl<T> IoVecBuf for SliceVec<T>
156// where
157// T: Shared,
158// {
159// fn stable_iovec_ptr(&self) -> *const libc::iovec {
160// self.iovecs.as_ptr()
161
162// // self.iovecs.clear();
163// // self.iovecs.reserve(self.indices.len());
164// // let base = self.buf.stable_ptr();
165// // for (begin, end) in self.indices.iter() {
166// // self.iovecs.push(libc::iovec {
167// // iov_base: unsafe { base.add(*begin) as *mut libc::c_void
168// }, // iov_len: end - begin,
169// // });
170// // }
171// // self.iovecs.as_ptr()
172// }
173
174// fn iovec_len(&self) -> usize {
175// self.indices.len()
176// }
177// }
178
179// impl<T> SliceVec<T> where T: Shared {
180// pub fn write_all(&mut self, data: &[u8]) -> Result<(), std::io::Error> {
181// unimplemented!()
182// }
183// }
184
185/// A mutable `io_uring` compatible iovec buffer.
186///
187/// # Safety
188/// See the safety note of the methods.
189#[allow(clippy::unnecessary_safety_doc)]
190pub unsafe trait IoVecBufMut: Unpin + 'static {
191 /// Returns a raw mutable pointer to iovec struct.
192 /// struct iovec {
193 /// void *iov_base; /* Starting address */
194 /// size_t iov_len; /* Number of bytes to transfer */
195 /// };
196 /// \[iovec1\]\[iovec2\]\[iovec3\]...
197 /// ^ The pointer
198 ///
199 /// # Safety
200 /// The implementation must ensure that, while the runtime owns the value,
201 /// the pointer returned by `write_iovec_ptr` **does not** change.
202 /// Also, the value pointed must be a valid iovec struct.
203 #[cfg(unix)]
204 fn write_iovec_ptr(&mut self) -> *mut libc::iovec;
205
206 /// Returns the count of iovec struct behind the pointer.
207 #[cfg(unix)]
208 fn write_iovec_len(&mut self) -> usize;
209
210 /// Returns a raw mutable pointer to WSABUF struct.
211 #[cfg(windows)]
212 fn write_wsabuf_ptr(&mut self) -> *mut WSABUF;
213
214 /// Returns the count of WSABUF struct behind the pointer.
215 #[cfg(windows)]
216 fn write_wsabuf_len(&mut self) -> usize;
217
218 /// Updates the number of initialized bytes.
219 ///
220 /// The specified `pos` becomes the new value returned by
221 /// `IoBuf::bytes_init`.
222 ///
223 /// # Safety
224 ///
225 /// The caller must ensure that there are really pos data initialized.
226 unsafe fn set_init(&mut self, pos: usize);
227}
228
229#[cfg(unix)]
230unsafe impl IoVecBufMut for VecBuf {
231 fn write_iovec_ptr(&mut self) -> *mut libc::iovec {
232 self.read_iovec_ptr() as *mut _
233 }
234
235 fn write_iovec_len(&mut self) -> usize {
236 self.read_iovec_len()
237 }
238
239 unsafe fn set_init(&mut self, mut len: usize) {
240 for (idx, iovec) in self.iovecs.iter_mut().enumerate() {
241 if iovec.iov_len <= len {
242 // set_init all
243 self.raw[idx].set_len(iovec.iov_len);
244 len -= iovec.iov_len;
245 } else {
246 if len > 0 {
247 self.raw[idx].set_len(len);
248 }
249 break;
250 }
251 }
252 }
253}
254
255#[cfg(windows)]
256unsafe impl IoVecBufMut for VecBuf {
257 fn write_wsabuf_ptr(&mut self) -> *mut WSABUF {
258 self.read_wsabuf_ptr() as *mut _
259 }
260
261 fn write_wsabuf_len(&mut self) -> usize {
262 self.read_wsabuf_len()
263 }
264
265 unsafe fn set_init(&mut self, mut len: usize) {
266 for (idx, wsabuf) in self.wsabufs.iter_mut().enumerate() {
267 if wsabuf.len as usize <= len {
268 // set_init all
269 self.raw[idx].set_len(wsabuf.len as _);
270 len -= wsabuf.len as usize;
271 } else {
272 if len > 0 {
273 self.raw[idx].set_len(len);
274 }
275 break;
276 }
277 }
278 }
279}