tokio_io_utility/
reusable_io_slices.rs
1use std::{
2 io::IoSlice,
3 mem::{ManuallyDrop, MaybeUninit},
4 num::NonZeroUsize,
5 ptr::NonNull,
6 slice::{from_raw_parts, from_raw_parts_mut},
7};
8
9#[derive(Debug)]
12pub struct ReusableIoSlices {
13 ptr: NonNull<()>,
14 cap: NonZeroUsize,
15}
16
17unsafe impl Send for ReusableIoSlices {}
18unsafe impl Sync for ReusableIoSlices {}
19
20impl ReusableIoSlices {
21 pub fn new(cap: NonZeroUsize) -> Self {
23 let mut v = ManuallyDrop::new(Vec::<MaybeUninit<IoSlice<'_>>>::with_capacity(cap.get()));
24
25 debug_assert_eq!(v.capacity(), cap.get());
26 debug_assert_eq!(v.len(), 0);
27
28 let ptr = v.as_mut_ptr();
29
30 let ptr = unsafe { NonNull::new_unchecked(ptr as *mut ()) };
38
39 Self { ptr, cap }
40 }
41
42 pub fn get_mut(&mut self) -> &mut [MaybeUninit<IoSlice<'_>>] {
44 unsafe {
45 from_raw_parts_mut(
46 self.ptr.as_ptr() as *mut MaybeUninit<IoSlice<'_>>,
47 self.cap.get(),
48 )
49 }
50 }
51
52 pub fn get(&self) -> &[MaybeUninit<IoSlice<'_>>] {
54 unsafe {
55 from_raw_parts(
56 self.ptr.as_ptr() as *const MaybeUninit<IoSlice<'_>>,
57 self.cap.get(),
58 )
59 }
60 }
61}
62
63impl Drop for ReusableIoSlices {
64 fn drop(&mut self) {
65 let ptr = self.ptr.as_ptr() as *mut MaybeUninit<IoSlice<'_>>;
67
68 let v: Vec<MaybeUninit<IoSlice<'_>>> =
76 unsafe { Vec::from_raw_parts(ptr, 0, self.cap.get()) };
77
78 drop(v);
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_reusable_io_slices() {
88 let io_slice = IoSlice::new(b"123exr3x");
89
90 for size in 1..300 {
91 let cap = NonZeroUsize::new(size).unwrap();
92 let mut reusable_io_slices = ReusableIoSlices::new(cap);
93
94 for uninit_io_slice in reusable_io_slices.get_mut() {
95 uninit_io_slice.write(io_slice);
96 }
97 }
98 }
99}