1pub mod slice;
2
3#[cfg(feature = "alloc")]
4use alloc::vec::Vec;
5use core::ops::{Bound, RangeBounds};
6
7use slice::{Buf, BufLayout, BufMut, BufMutLayout};
8
9use crate::{maybe::MaybeOwned, MaybeSend};
10
11pub trait IoBuf: Unpin + Sized + MaybeOwned + MaybeSend {
33 fn as_ptr(&self) -> *const u8;
34
35 fn bytes_init(&self) -> usize;
36
37 fn as_slice(&self) -> &[u8] {
38 unsafe { core::slice::from_raw_parts(self.as_ptr(), self.bytes_init()) }
40 }
41
42 #[cfg(feature = "bytes")]
43 fn as_bytes(&self) -> bytes::Bytes {
44 bytes::Bytes::copy_from_slice(self.as_slice())
45 }
46
47 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf;
56
57 unsafe fn recover_from_slice(buf: Buf) -> Self;
66
67 fn calculate_bounds<R: RangeBounds<usize>>(&self, range: R) -> (usize, usize) {
68 let start = match range.start_bound() {
69 Bound::Included(&start) => start,
70 Bound::Excluded(&start) => start + 1,
71 Bound::Unbounded => 0,
72 };
73 let end = match range.end_bound() {
74 Bound::Included(&end) => end + 1,
75 Bound::Excluded(&end) => end,
76 Bound::Unbounded => self.bytes_init(),
77 };
78 (start, end)
79 }
80}
81
82pub trait IoBufMut: IoBuf {
84 fn as_mut_ptr(&mut self) -> *mut u8;
85
86 fn as_slice_mut(&mut self) -> &mut [u8] {
87 unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.bytes_init()) }
89 }
90
91 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut;
100
101 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self;
110}
111
112#[cfg(feature = "alloc")]
113impl IoBuf for Vec<u8> {
114 fn as_ptr(&self) -> *const u8 {
115 self.as_ptr()
116 }
117
118 fn bytes_init(&self) -> usize {
119 self.len()
120 }
121
122 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
123 let (start, end) = self.calculate_bounds(range);
124 Buf {
125 layout: BufLayout::Vec(self),
126 start,
127 end,
128 }
129 }
130
131 unsafe fn recover_from_slice(buf: Buf) -> Self {
132 match buf.layout {
133 BufLayout::Vec(vec) => vec,
134 _ => unreachable!(),
135 }
136 }
137}
138
139#[cfg(feature = "alloc")]
140impl IoBufMut for Vec<u8> {
141 fn as_mut_ptr(&mut self) -> *mut u8 {
142 Vec::as_mut_ptr(self)
143 }
144
145 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
146 let (start, end) = self.calculate_bounds(range);
147 BufMut {
148 layout: BufMutLayout::Vec(self),
149 start,
150 end,
151 }
152 }
153
154 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
155 match buf.layout {
156 BufMutLayout::Vec(vec) => vec,
157 _ => unreachable!(),
158 }
159 }
160}
161
162#[cfg(not(feature = "completion-based"))]
163impl IoBuf for &[u8] {
164 fn as_ptr(&self) -> *const u8 {
165 (*self).as_ptr()
166 }
167
168 fn bytes_init(&self) -> usize {
169 self.len()
170 }
171
172 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
173 let (start, end) = self.calculate_bounds(range);
174 Buf {
175 layout: BufLayout::Slice {
176 ptr: self.as_ptr() as *mut u8,
177 len: self.len(),
178 },
179 start,
180 end,
181 }
182 }
183
184 unsafe fn recover_from_slice(buf: Buf) -> Self {
185 match buf.layout {
186 BufLayout::Slice { ptr, len } => core::slice::from_raw_parts(ptr, len),
187 _ => unreachable!(),
188 }
189 }
190}
191
192#[cfg(not(feature = "completion-based"))]
193impl IoBuf for &mut [u8] {
194 fn as_ptr(&self) -> *const u8 {
195 <[u8]>::as_ptr(self)
196 }
197
198 fn bytes_init(&self) -> usize {
199 self.len()
200 }
201
202 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
203 let (start, end) = self.calculate_bounds(range);
204 Buf {
205 layout: BufLayout::Slice {
206 ptr: self.as_ptr() as *mut u8,
207 len: self.len(),
208 },
209 start,
210 end,
211 }
212 }
213
214 unsafe fn recover_from_slice(buf: Buf) -> Self {
215 match buf.layout {
216 BufLayout::Slice { ptr, len } => core::slice::from_raw_parts_mut(ptr as *mut u8, len),
217 _ => unreachable!(),
218 }
219 }
220}
221
222#[cfg(not(feature = "completion-based"))]
223impl IoBufMut for &mut [u8] {
224 fn as_mut_ptr(&mut self) -> *mut u8 {
225 <[u8]>::as_mut_ptr(self)
226 }
227
228 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
229 let (start, end) = self.calculate_bounds(range);
230 BufMut {
231 layout: BufMutLayout::Slice {
232 ptr: self.as_mut_ptr(),
233 len: self.len(),
234 },
235 start,
236 end,
237 }
238 }
239
240 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
241 match buf.layout {
242 BufMutLayout::Slice { ptr, len } => core::slice::from_raw_parts_mut(ptr, len),
243 _ => unreachable!(),
244 }
245 }
246}
247
248#[cfg(feature = "completion-based")]
249impl IoBuf for &'static [u8] {
250 fn as_ptr(&self) -> *const u8 {
251 (*self).as_ptr()
252 }
253
254 fn bytes_init(&self) -> usize {
255 self.len()
256 }
257
258 #[cfg(feature = "bytes")]
259 fn as_bytes(&self) -> bytes::Bytes {
260 bytes::Bytes::from_static(self)
261 }
262
263 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
264 let (start, end) = self.calculate_bounds(range);
265 Buf {
266 layout: BufLayout::Slice {
267 ptr: self.as_ptr() as *mut u8,
268 len: self.len(),
269 },
270 start,
271 end,
272 }
273 }
274
275 unsafe fn recover_from_slice(buf: Buf) -> Self {
276 match buf.layout {
277 BufLayout::Slice { ptr, len } => core::slice::from_raw_parts(ptr, len),
278 _ => unreachable!(),
279 }
280 }
281}
282
283#[cfg(feature = "bytes")]
284impl IoBuf for bytes::Bytes {
285 fn as_ptr(&self) -> *const u8 {
286 <[u8]>::as_ptr(self)
287 }
288
289 fn bytes_init(&self) -> usize {
290 self.len()
291 }
292 fn as_bytes(&self) -> bytes::Bytes {
293 self.clone()
294 }
295
296 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
297 let start = match range.start_bound() {
298 Bound::Included(&start) => start,
299 Bound::Excluded(&start) => start + 1,
300 Bound::Unbounded => 0,
301 };
302 let end = match range.end_bound() {
303 Bound::Included(&end) => end + 1,
304 Bound::Excluded(&end) => end,
305 Bound::Unbounded => self.len(),
306 };
307 Buf {
308 layout: BufLayout::Bytes(self),
309 start,
310 end,
311 }
312 }
313
314 unsafe fn recover_from_slice(buf: Buf) -> Self {
315 match buf.layout {
316 BufLayout::Bytes(bytes) => bytes,
317 _ => unreachable!(),
318 }
319 }
320}
321
322#[cfg(feature = "bytes")]
323impl IoBuf for bytes::BytesMut {
324 fn as_ptr(&self) -> *const u8 {
325 <[u8]>::as_ptr(self)
326 }
327
328 fn bytes_init(&self) -> usize {
329 self.len()
330 }
331
332 fn as_bytes(&self) -> bytes::Bytes {
333 self.clone().freeze()
334 }
335
336 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
337 let start = match range.start_bound() {
338 Bound::Included(&start) => start,
339 Bound::Excluded(&start) => start + 1,
340 Bound::Unbounded => 0,
341 };
342 let end = match range.end_bound() {
343 Bound::Included(&end) => end + 1,
344 Bound::Excluded(&end) => end,
345 Bound::Unbounded => self.len(),
346 };
347 Buf {
348 layout: BufLayout::BytesMut(self),
349 start,
350 end,
351 }
352 }
353
354 unsafe fn recover_from_slice(buf: Buf) -> Self {
355 match buf.layout {
356 BufLayout::BytesMut(bytes) => bytes,
357 _ => unreachable!(),
358 }
359 }
360}
361
362#[cfg(feature = "bytes")]
363impl IoBufMut for bytes::BytesMut {
364 fn as_mut_ptr(&mut self) -> *mut u8 {
365 <[u8]>::as_mut_ptr(self)
366 }
367
368 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
369 let start = match range.start_bound() {
370 Bound::Included(&start) => start,
371 Bound::Excluded(&start) => start + 1,
372 Bound::Unbounded => 0,
373 };
374 let end = match range.end_bound() {
375 Bound::Included(&end) => end + 1,
376 Bound::Excluded(&end) => end,
377 Bound::Unbounded => self.len(),
378 };
379 BufMut {
380 layout: BufMutLayout::BytesMut(self),
381 start,
382 end,
383 }
384 }
385
386 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
387 match buf.layout {
388 BufMutLayout::BytesMut(bytes) => bytes,
389 _ => unreachable!(),
390 }
391 }
392}