1use std::{iter, mem::MaybeUninit};
2
3use crate::{IntoInner, IoBuf, IoBufMut, IoBufMutExt, SetLen, VectoredSlice, t_alloc};
4
5pub trait IoVectoredBuf: 'static {
13 fn iter_slice(&self) -> impl Iterator<Item = &[u8]>;
15
16 fn total_len(&self) -> usize {
18 self.iter_slice().map(|buf| buf.len()).sum()
19 }
20
21 fn owned_iter(self) -> Result<VectoredBufIter<Self>, Self>
23 where
24 Self: Sized,
25 {
26 VectoredBufIter::new(self)
27 }
28
29 fn slice(self, begin: usize) -> VectoredSlice<Self>
63 where
64 Self: Sized,
65 {
66 let mut offset = begin;
67 let mut idx = 0;
68
69 for b in self.iter_slice() {
70 let len = b.len();
71 if len > offset {
72 break;
73 }
74 offset -= len;
75 idx += 1;
76 }
77
78 VectoredSlice::new(self, begin, idx, offset)
79 }
80}
81
82impl<T: IoBuf> IoVectoredBuf for &'static [T] {
83 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
84 self.iter().map(|buf| buf.as_init())
85 }
86}
87
88impl<T: IoBuf> IoVectoredBuf for &'static mut [T] {
89 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
90 self.iter().map(|buf| buf.as_init())
91 }
92}
93
94impl<T: IoBuf, const N: usize> IoVectoredBuf for [T; N] {
95 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
96 self.iter().map(|buf| buf.as_init())
97 }
98}
99
100impl<T: IoBuf, #[cfg(feature = "allocator_api")] A: std::alloc::Allocator + 'static> IoVectoredBuf
101 for t_alloc!(Vec, T, A)
102{
103 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
104 self.iter().map(|buf| buf.as_init())
105 }
106}
107
108#[cfg(feature = "arrayvec")]
109impl<T: IoBuf, const N: usize> IoVectoredBuf for arrayvec::ArrayVec<T, N> {
110 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
111 self.iter().map(|buf| buf.as_init())
112 }
113}
114
115#[cfg(feature = "smallvec")]
116impl<T: IoBuf, const N: usize> IoVectoredBuf for smallvec::SmallVec<[T; N]>
117where
118 [T; N]: smallvec::Array<Item = T>,
119{
120 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
121 self.iter().map(|buf| buf.as_init())
122 }
123}
124
125impl<T: IoBuf, Rest: IoVectoredBuf> IoVectoredBuf for (T, Rest) {
126 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
127 std::iter::once(self.0.as_init()).chain(self.1.iter_slice())
128 }
129}
130
131impl<T: IoBuf> IoVectoredBuf for (T,) {
132 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
133 std::iter::once(self.0.as_init())
134 }
135}
136
137impl IoVectoredBuf for () {
138 fn iter_slice(&self) -> impl Iterator<Item = &[u8]> {
139 std::iter::empty()
140 }
141}
142
143pub trait IoVectoredBufMut: IoVectoredBuf + SetLen {
145 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]>;
152
153 fn total_capacity(&mut self) -> usize {
155 unsafe { self.iter_uninit_slice() }
157 .map(|buf| buf.len())
158 .sum()
159 }
160
161 fn slice_mut(mut self, begin: usize) -> VectoredSlice<Self>
189 where
190 Self: Sized,
191 {
192 let mut offset = begin;
193 let mut idx = 0;
194
195 for b in unsafe { self.iter_uninit_slice() } {
198 let len = b.len();
199 if len > offset {
200 break;
201 }
202 offset -= len;
203 idx += 1;
204 }
205
206 VectoredSlice::new(self, begin, idx, offset)
207 }
208}
209
210impl<T: IoBufMut> IoVectoredBufMut for &'static mut [T] {
211 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
212 self.iter_mut().map(|buf| unsafe { buf.as_uninit() })
213 }
214}
215
216impl<T: IoBufMut, const N: usize> IoVectoredBufMut for [T; N] {
217 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
218 self.iter_mut().map(|buf| unsafe { buf.as_uninit() })
219 }
220}
221
222impl<T: IoBufMut, #[cfg(feature = "allocator_api")] A: std::alloc::Allocator + 'static>
223 IoVectoredBufMut for t_alloc!(Vec, T, A)
224{
225 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
226 self.iter_mut().map(|buf| unsafe { buf.as_uninit() })
227 }
228}
229
230#[cfg(feature = "arrayvec")]
231impl<T: IoBufMut, const N: usize> IoVectoredBufMut for arrayvec::ArrayVec<T, N> {
232 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
233 self.iter_mut().map(|buf| unsafe { buf.as_uninit() })
234 }
235}
236
237#[cfg(feature = "smallvec")]
238impl<T: IoBufMut, const N: usize> IoVectoredBufMut for smallvec::SmallVec<[T; N]>
239where
240 [T; N]: smallvec::Array<Item = T>,
241{
242 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
243 self.iter_mut().map(|buf| unsafe { buf.as_uninit() })
244 }
245}
246
247impl<T: IoBufMut, Rest: IoVectoredBufMut> IoVectoredBufMut for (T, Rest) {
248 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
249 let (h, t) = self;
250 unsafe { iter::once(h.as_uninit()).chain(t.iter_uninit_slice()) }
251 }
252}
253
254impl<T: IoBufMut> IoVectoredBufMut for (T,) {
255 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
256 iter::once(unsafe { self.0.as_uninit() })
257 }
258}
259
260impl IoVectoredBufMut for () {
261 unsafe fn iter_uninit_slice(&mut self) -> impl Iterator<Item = &mut [MaybeUninit<u8>]> {
262 iter::empty()
263 }
264}
265
266impl<T: IoBufMut, Rest: IoVectoredBufMut> SetLen for (T, Rest) {
267 unsafe fn set_len(&mut self, len: usize) {
268 let head_len = std::cmp::min(len, self.0.buf_capacity());
269 let rest_len = len - head_len;
270
271 unsafe { self.0.set_len(head_len) };
273 unsafe { self.1.set_len(rest_len) };
275 }
276}
277
278impl<T: IoBufMut> SetLen for (T,) {
279 unsafe fn set_len(&mut self, len: usize) {
280 unsafe { self.0.set_len(len) };
281 }
282}
283
284impl SetLen for () {
285 unsafe fn set_len(&mut self, len: usize) {
286 assert_eq!(len, 0, "set_len called with non-zero len on empty buffer");
287 }
288}
289
290pub struct VectoredBufIter<T> {
295 buf: T,
296 total_filled: usize,
297 index: usize,
298 len: usize,
299 filled: usize,
300}
301
302impl<T> VectoredBufIter<T> {
303 pub fn next(mut self) -> Result<Self, T> {
306 self.index += 1;
307 if self.index < self.len {
308 self.total_filled += self.filled;
309 self.filled = 0;
310 Ok(self)
311 } else {
312 Err(self.buf)
313 }
314 }
315}
316
317impl<T: IoVectoredBuf> VectoredBufIter<T> {
318 fn new(buf: T) -> Result<Self, T> {
319 let len = buf.iter_slice().count();
320 if len > 0 {
321 Ok(Self {
322 buf,
323 index: 0,
324 len,
325 total_filled: 0,
326 filled: 0,
327 })
328 } else {
329 Err(buf)
330 }
331 }
332}
333
334impl<T> IntoInner for VectoredBufIter<T> {
335 type Inner = T;
336
337 fn into_inner(self) -> Self::Inner {
338 self.buf
339 }
340}
341
342impl<T: IoVectoredBuf> IoBuf for VectoredBufIter<T> {
343 fn as_init(&self) -> &[u8] {
344 let curr = self
345 .buf
346 .iter_slice()
347 .nth(self.index)
348 .expect("`index` should not exceed `len`");
349
350 &curr[self.filled..]
351 }
352}
353
354impl<T: IoVectoredBuf + SetLen> SetLen for VectoredBufIter<T> {
355 unsafe fn set_len(&mut self, len: usize) {
356 self.filled = len;
357
358 unsafe { self.buf.set_len(self.total_filled + self.filled) };
359 }
360}
361
362impl<T: IoVectoredBufMut> IoBufMut for VectoredBufIter<T> {
363 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
364 let filled = self.filled;
365 let curr = unsafe {
368 self.buf
369 .iter_uninit_slice()
370 .nth(self.index)
371 .expect("`index` should not exceed `len`")
372 };
373 &mut curr[filled..]
374 }
375}
376
377#[cfg(test)]
378mod test {
379 use std::mem::MaybeUninit;
380
381 use crate::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, SetLen};
382
383 #[test]
384 fn vectored_buf_iter_uninit_skips_filled() {
385 let bufs = [Vec::with_capacity(8), Vec::with_capacity(8)];
386 let mut iter = bufs.owned_iter().unwrap();
387
388 unsafe {
391 let slice = iter.as_uninit();
392 assert_eq!(slice.len(), 8);
393 slice[..3].fill(MaybeUninit::new(7));
394 iter.set_len(3);
396 }
397
398 assert!(iter.as_init().is_empty());
400
401 let tail = unsafe { iter.as_uninit() };
404 assert_eq!(tail.len(), 5);
405 tail[..2].fill(MaybeUninit::new(9));
406
407 let bufs = iter.into_inner();
408 assert_eq!(bufs[0].as_init(), &[7, 7, 7]);
409 assert_eq!(bufs[1].as_init(), &[]);
410 }
411}