1use std::mem::{size_of, MaybeUninit};
4
5use bytes::BytesMut;
6use zerocopy::{AsBytes, FromBytes};
7
8pub unsafe trait IoBuf: Unpin + 'static {
9 fn stable_ptr(&self) -> *const u8;
18
19 fn bytes_init(&self) -> usize;
26
27 fn bytes_total(&self) -> usize;
34}
35
36pub unsafe trait IoBufMut: IoBuf {
47 fn stable_mut_ptr(&mut self) -> *mut u8;
56
57 unsafe fn set_init(&mut self, pos: usize);
67}
68
69unsafe impl<T: IoBufMut> IoBufMut for Box<T> {
70 fn stable_mut_ptr(&mut self) -> *mut u8 {
71 self.as_mut().stable_mut_ptr()
72 }
73
74 unsafe fn set_init(&mut self, pos: usize) {
75 self.as_mut().set_init(pos)
76 }
77}
78
79unsafe impl IoBuf for BytesMut {
80 fn stable_ptr(&self) -> *const u8 {
81 self.as_ptr()
82 }
83
84 fn bytes_init(&self) -> usize {
85 self.len()
86 }
87
88 fn bytes_total(&self) -> usize {
89 self.capacity()
90 }
91}
92
93unsafe impl IoBufMut for BytesMut {
94 fn stable_mut_ptr(&mut self) -> *mut u8 {
95 self.as_mut_ptr()
96 }
97
98 unsafe fn set_init(&mut self, pos: usize) {
99 unsafe { self.set_len(pos) }
100 }
101}
102
103unsafe impl<T: IoBuf> IoBuf for Box<T> {
104 fn stable_ptr(&self) -> *const u8 {
105 self.as_ref().stable_ptr()
106 }
107
108 fn bytes_init(&self) -> usize {
109 self.as_ref().bytes_init()
110 }
111
112 fn bytes_total(&self) -> usize {
113 self.as_ref().bytes_total()
114 }
115}
116
117pub struct ZeroCopyBuf<T> {
118 init: usize,
119 inner: MaybeUninit<T>,
120}
121
122pub struct ZeroCopyBoxIoBuf<T> {
123 inner: Box<T>,
124 init: usize,
125}
126
127impl<T> ZeroCopyBoxIoBuf<T> {
128 pub fn new(inner: Box<T>) -> Self {
129 Self {
130 init: size_of::<T>(),
131 inner,
132 }
133 }
134
135 pub fn new_uninit(inner: Box<T>) -> Self {
136 Self { init: 0, inner }
137 }
138
139 fn is_init(&self) -> bool {
140 self.init == size_of::<T>()
141 }
142
143 pub fn into_inner(self) -> Box<T> {
144 assert!(self.is_init());
145 self.inner
146 }
147}
148
149unsafe impl<T: AsBytes + Unpin + 'static> IoBuf for ZeroCopyBoxIoBuf<T> {
150 fn stable_ptr(&self) -> *const u8 {
151 T::as_bytes(&self.inner).as_ptr()
152 }
153
154 fn bytes_init(&self) -> usize {
155 self.init
156 }
157
158 fn bytes_total(&self) -> usize {
159 size_of::<T>()
160 }
161}
162
163unsafe impl<T: AsBytes + FromBytes + Unpin + 'static> IoBufMut for ZeroCopyBoxIoBuf<T> {
164 fn stable_mut_ptr(&mut self) -> *mut u8 {
165 T::as_bytes_mut(&mut self.inner).as_mut_ptr()
166 }
167
168 unsafe fn set_init(&mut self, pos: usize) {
169 self.init = pos;
170 }
171}
172
173impl<T> ZeroCopyBuf<T> {
174 pub fn new_init(inner: T) -> Self {
175 Self {
176 inner: MaybeUninit::new(inner),
177 init: size_of::<T>(),
178 }
179 }
180
181 pub fn new_uninit() -> Self {
182 Self {
183 init: 0,
184 inner: MaybeUninit::uninit(),
185 }
186 }
187
188 pub fn map_slice<F>(self, f: F) -> MapSlice<T, F>
189 where
190 for<'a> F: Fn(&'a Self) -> &'a [u8] + Unpin + 'static,
191 {
192 MapSlice { inner: self, f }
193 }
194
195 #[inline]
196 pub fn is_init(&self) -> bool {
197 self.init == size_of::<T>()
198 }
199
200 pub fn get_ref(&self) -> &T {
204 assert!(self.is_init());
205 unsafe { self.inner.assume_init_ref() }
206 }
207
208 pub fn get_mut(&mut self) -> &mut T {
209 assert!(self.is_init());
210 unsafe { self.inner.assume_init_mut() }
211 }
212
213 pub fn into_inner(self) -> T {
214 assert!(self.is_init());
215 unsafe { self.inner.assume_init() }
216 }
217
218 pub fn deinit(&mut self) {
219 self.init = 0;
220 }
221}
222
223pub struct MapSlice<T, F> {
224 inner: ZeroCopyBuf<T>,
225 f: F,
226}
227
228impl<T, F> MapSlice<T, F> {
229 pub(crate) fn into_inner(self) -> ZeroCopyBuf<T> {
230 self.inner
231 }
232}
233
234unsafe impl<T, F> IoBuf for MapSlice<T, F>
235where
236 for<'a> F: Fn(&'a ZeroCopyBuf<T>) -> &'a [u8] + Unpin + 'static,
237 T: Unpin + 'static + AsBytes,
238{
239 fn stable_ptr(&self) -> *const u8 {
240 (self.f)(&self.inner).as_ptr()
241 }
242
243 fn bytes_init(&self) -> usize {
244 (self.f)(&self.inner).len()
245 }
246
247 fn bytes_total(&self) -> usize {
248 (self.f)(&self.inner).len()
249 }
250}
251
252unsafe impl<T: AsBytes + Unpin + 'static> IoBuf for ZeroCopyBuf<T> {
253 fn stable_ptr(&self) -> *const u8 {
254 self.inner.as_ptr() as *const _
255 }
256
257 fn bytes_init(&self) -> usize {
258 self.init
259 }
260
261 fn bytes_total(&self) -> usize {
262 size_of::<T>()
263 }
264}
265
266unsafe impl<T: AsBytes + Unpin + 'static> IoBufMut for ZeroCopyBuf<T> {
267 fn stable_mut_ptr(&mut self) -> *mut u8 {
268 self.inner.as_mut_ptr() as *mut _
269 }
270
271 unsafe fn set_init(&mut self, pos: usize) {
272 assert!(pos <= size_of::<T>());
273 self.init = pos
274 }
275}
276
277unsafe impl IoBufMut for Vec<u8> {
278 fn stable_mut_ptr(&mut self) -> *mut u8 {
279 self.as_mut_ptr()
280 }
281
282 unsafe fn set_init(&mut self, init_len: usize) {
283 if self.len() < init_len {
284 self.set_len(init_len);
285 }
286 }
287}
288
289unsafe impl IoBuf for Vec<u8> {
290 fn stable_ptr(&self) -> *const u8 {
291 self.as_ptr()
292 }
293
294 fn bytes_init(&self) -> usize {
295 self.len()
296 }
297
298 fn bytes_total(&self) -> usize {
299 self.capacity()
300 }
301}