1use core::mem::MaybeUninit;
6
7use super::owned::{IoBuf, IoBufMut, OwnedBuf};
8
9mod sealed {
10 use super::OwnedBuf;
11
12 pub struct Bufs(pub(crate) Vec<OwnedBuf>);
14
15 pub trait Written: Sized {
18 fn into_owned(self) -> Bufs;
19 fn from_owned(bufs: Bufs) -> Self;
20 }
21
22 pub trait Filled: Sized {
24 fn into_owned(self) -> Bufs;
25 fn from_owned(bufs: Bufs) -> Self;
26 }
27}
28
29use sealed::Bufs;
30
31pub trait IoVecBuf: sealed::Written + Send + 'static {}
35
36pub trait IoVecBufMut: sealed::Filled + Send + 'static {}
40
41impl<B> sealed::Written for Vec<B>
42where
43 B: IoBuf,
44{
45 fn into_owned(self) -> Bufs {
46 Bufs(self.into_iter().map(OwnedBuf::written).collect())
47 }
48
49 fn from_owned(bufs: Bufs) -> Self {
50 bufs.0.into_iter().map(OwnedBuf::into_written).collect()
51 }
52}
53
54impl<B> IoVecBuf for Vec<B> where B: IoBuf {}
55
56impl<B> sealed::Filled for Vec<B>
57where
58 B: IoBufMut,
59{
60 fn into_owned(self) -> Bufs {
61 Bufs(self.into_iter().map(OwnedBuf::filled).collect())
62 }
63
64 fn from_owned(bufs: Bufs) -> Self {
65 bufs.0.into_iter().map(OwnedBuf::into_filled).collect()
66 }
67}
68
69impl<B> IoVecBufMut for Vec<B> where B: IoBufMut {}
70
71impl<B, const N: usize> sealed::Written for [B; N]
72where
73 B: IoBuf,
74{
75 fn into_owned(self) -> Bufs {
76 Bufs(self.into_iter().map(OwnedBuf::written).collect())
77 }
78
79 fn from_owned(bufs: Bufs) -> Self {
80 let mut bufs = bufs.0.into_iter();
81 core::array::from_fn(|_| bufs.next().map_or_else(B::default, OwnedBuf::into_written))
82 }
83}
84
85impl<B, const N: usize> IoVecBuf for [B; N] where B: IoBuf {}
86
87impl<B, const N: usize> sealed::Filled for [B; N]
88where
89 B: IoBufMut,
90{
91 fn into_owned(self) -> Bufs {
92 Bufs(self.into_iter().map(OwnedBuf::filled).collect())
93 }
94
95 fn from_owned(bufs: Bufs) -> Self {
96 let mut bufs = bufs.0.into_iter();
97 core::array::from_fn(|_| bufs.next().map_or_else(B::default, OwnedBuf::into_filled))
98 }
99}
100
101impl<B, const N: usize> IoVecBufMut for [B; N] where B: IoBufMut {}
102
103pub(crate) fn written<V>(bufs: V) -> Vec<OwnedBuf>
105where
106 V: IoVecBuf,
107{
108 sealed::Written::into_owned(bufs).0
109}
110
111pub(crate) fn into_written<V>(bufs: Vec<OwnedBuf>) -> V
113where
114 V: IoVecBuf,
115{
116 <V as sealed::Written>::from_owned(Bufs(bufs))
117}
118
119pub(crate) fn filled<V>(bufs: V) -> Vec<OwnedBuf>
121where
122 V: IoVecBufMut,
123{
124 sealed::Filled::into_owned(bufs).0
125}
126
127pub(crate) fn into_filled<V>(bufs: Vec<OwnedBuf>) -> V
129where
130 V: IoVecBufMut,
131{
132 <V as sealed::Filled>::from_owned(Bufs(bufs))
133}
134
135#[cfg(unix)]
138pub(crate) type IoVec = libc::iovec;
139#[cfg(windows)]
140pub(crate) type IoVec = crate::syscore::windows::WSABUF;
141
142pub(crate) const IOV_MAX: usize = 1024;
146
147fn iovec(ptr: *const u8, len: usize) -> IoVec {
148 #[cfg(unix)]
149 return libc::iovec {
150 iov_base: ptr.cast_mut().cast(),
151 iov_len: len,
152 };
153 #[cfg(windows)]
154 return IoVec {
155 len: u32::try_from(len).unwrap_or(u32::MAX),
156 buf: ptr.cast_mut(),
157 };
158}
159
160pub(crate) struct Vectored {
164 bufs: Vec<OwnedBuf>,
165 held: Option<Vec<usize>>,
168 iov: Vec<IoVec>,
171 #[cfg(ring)]
173 msg: libc::msghdr,
174}
175
176unsafe impl Send for Vectored {}
179unsafe impl Sync for Vectored {}
181
182impl Vectored {
183 fn new(bufs: Vec<OwnedBuf>, held: Option<Vec<usize>>) -> Self {
184 Self {
185 bufs,
186 held,
187 iov: Vec::new(),
188 #[cfg(ring)]
190 msg: unsafe { core::mem::zeroed() },
191 }
192 }
193
194 pub(crate) fn written(bufs: Vec<OwnedBuf>) -> Self {
196 Self::new(bufs, None)
197 }
198
199 pub(crate) fn filled(bufs: Vec<OwnedBuf>) -> Self {
201 let held = bufs.iter().map(OwnedBuf::len).collect();
202 Self::new(bufs, Some(held))
203 }
204
205 pub(crate) fn into_bufs(self) -> Vec<OwnedBuf> {
206 self.bufs
207 }
208
209 pub(crate) fn len(&self) -> usize {
211 self.bufs.iter().map(OwnedBuf::len).sum()
212 }
213
214 pub(crate) fn capacity(&self) -> usize {
217 match self.held {
218 Some(_) => self.bufs.iter().map(OwnedBuf::capacity).sum(),
219 None => self.len(),
220 }
221 }
222
223 pub(crate) fn rest_from(&self, from: usize) -> &[u8] {
226 let mut from = from;
227 for buf in &self.bufs {
228 if from < buf.len() {
229 return buf.rest_from(from);
230 }
231 from -= buf.len();
232 }
233 &[]
234 }
235
236 pub(crate) fn write_iovecs(&mut self, from: usize) -> &[IoVec] {
239 self.iov.clear();
240 let mut skip = from;
241 for buf in &self.bufs {
242 if self.iov.len() == IOV_MAX {
243 break;
244 }
245 let bytes = buf.rest_from(skip);
246 skip = skip.saturating_sub(buf.len());
247 if !bytes.is_empty() {
248 self.iov.push(iovec(bytes.as_ptr(), bytes.len()));
249 }
250 }
251 &self.iov
252 }
253
254 pub(crate) fn read_iovecs(&mut self) -> &mut [IoVec] {
258 self.iov.clear();
259 if self.held.is_some() {
260 for buf in &mut self.bufs {
261 if self.iov.len() == IOV_MAX {
262 break;
263 }
264 let room = buf.spare_capacity_mut();
265 if !room.is_empty() {
266 self.iov.push(iovec(room.as_mut_ptr().cast(), room.len()));
267 }
268 }
269 }
270 &mut self.iov
271 }
272
273 #[cfg(ring)]
276 pub(crate) fn send_msg(&mut self, from: usize) -> *const libc::msghdr {
277 let count = self.write_iovecs(from).len();
278 self.msg.msg_iov = self.iov.as_mut_ptr();
279 self.msg.msg_iovlen = count as _;
280 &raw const self.msg
281 }
282
283 #[cfg(ring)]
286 pub(crate) fn recv_msg(&mut self) -> *mut libc::msghdr {
287 let count = self.read_iovecs().len();
288 self.msg.msg_iov = self.iov.as_mut_ptr();
289 self.msg.msg_iovlen = count as _;
290 &raw mut self.msg
291 }
292
293 #[cfg(windows)]
296 pub(crate) fn built(&mut self) -> &mut [IoVec] {
297 &mut self.iov
298 }
299
300 pub(crate) fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<u8>] {
302 if self.held.is_none() {
303 return &mut [];
304 }
305 match self.bufs.iter_mut().find(|b| b.len() < b.capacity()) {
306 Some(buf) => buf.spare_capacity_mut(),
307 None => &mut [],
308 }
309 }
310
311 pub(crate) unsafe fn set_len(&mut self, len: usize) {
319 let Some(held) = &self.held else {
320 return;
321 };
322 let mut left = len.saturating_sub(held.iter().sum());
323 for (buf, &held) in self.bufs.iter_mut().zip(held) {
324 let take = left.min(buf.capacity() - held);
325 left -= take;
326 unsafe { buf.set_len(held + take) };
329 }
330 }
331
332 pub(crate) fn append(&mut self, bytes: &[u8]) -> usize {
335 if self.held.is_none() {
336 return 0;
337 }
338 let mut n = 0;
339 for buf in &mut self.bufs {
340 if n == bytes.len() {
341 break;
342 }
343 n += buf.append(&bytes[n..]);
344 }
345 n
346 }
347
348 pub(crate) fn read_parts(self) -> impl Iterator<Item = (OwnedBuf, usize)> {
351 let held = self.held.unwrap_or_default();
352 self.bufs
353 .into_iter()
354 .zip(held)
355 .filter(|(buf, held)| buf.len() > *held)
356 }
357}