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}