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 {
12 fn as_ptr(&self) -> *const u8;
20
21 fn bytes_init(&self) -> usize;
22
23 fn as_slice(&self) -> &[u8] {
24 unsafe { core::slice::from_raw_parts(self.as_ptr(), self.bytes_init()) }
26 }
27
28 #[cfg(feature = "bytes")]
29 fn as_bytes(&self) -> bytes::Bytes {
30 bytes::Bytes::copy_from_slice(self.as_slice())
31 }
32
33 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf;
36
37 unsafe fn recover_from_slice(buf: Buf) -> Self;
40
41 fn calculate_bounds<R: RangeBounds<usize>>(&self, range: R) -> (usize, usize) {
42 let start = match range.start_bound() {
43 Bound::Included(&start) => start,
44 Bound::Excluded(&start) => start + 1,
45 Bound::Unbounded => 0,
46 };
47 let end = match range.end_bound() {
48 Bound::Included(&end) => end + 1,
49 Bound::Excluded(&end) => end,
50 Bound::Unbounded => self.bytes_init(),
51 };
52 (start, end)
53 }
54}
55
56pub trait IoBufMut: IoBuf {
57 fn as_mut_ptr(&mut self) -> *mut u8;
60
61 fn as_slice_mut(&mut self) -> &mut [u8] {
62 unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.bytes_init()) }
64 }
65
66 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut;
69
70 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self;
73}
74
75#[cfg(feature = "alloc")]
76impl IoBuf for Vec<u8> {
77 fn as_ptr(&self) -> *const u8 {
78 self.as_ptr()
79 }
80
81 fn bytes_init(&self) -> usize {
82 self.len()
83 }
84
85 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
86 let (start, end) = self.calculate_bounds(range);
87 Buf {
88 layout: BufLayout::Vec(self),
89 start,
90 end,
91 }
92 }
93
94 unsafe fn recover_from_slice(buf: Buf) -> Self {
95 match buf.layout {
96 BufLayout::Vec(vec) => vec,
97 _ => unreachable!(),
98 }
99 }
100}
101
102#[cfg(feature = "alloc")]
103impl IoBufMut for Vec<u8> {
104 fn as_mut_ptr(&mut self) -> *mut u8 {
105 Vec::as_mut_ptr(self)
106 }
107
108 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
109 let (start, end) = self.calculate_bounds(range);
110 BufMut {
111 layout: BufMutLayout::Vec(self),
112 start,
113 end,
114 }
115 }
116
117 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
118 match buf.layout {
119 BufMutLayout::Vec(vec) => vec,
120 _ => unreachable!(),
121 }
122 }
123}
124
125#[cfg(not(feature = "completion-based"))]
126impl IoBuf for &[u8] {
127 fn as_ptr(&self) -> *const u8 {
128 (*self).as_ptr()
129 }
130
131 fn bytes_init(&self) -> usize {
132 self.len()
133 }
134
135 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
136 let (start, end) = self.calculate_bounds(range);
137 Buf {
138 layout: BufLayout::Slice {
139 ptr: self.as_ptr() as *mut u8,
140 len: self.len(),
141 },
142 start,
143 end,
144 }
145 }
146
147 unsafe fn recover_from_slice(buf: Buf) -> Self {
148 match buf.layout {
149 BufLayout::Slice { ptr, len } => core::slice::from_raw_parts(ptr, len),
150 _ => unreachable!(),
151 }
152 }
153}
154
155#[cfg(not(feature = "completion-based"))]
156impl IoBuf for &mut [u8] {
157 fn as_ptr(&self) -> *const u8 {
158 <[u8]>::as_ptr(self)
159 }
160
161 fn bytes_init(&self) -> usize {
162 self.len()
163 }
164
165 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
166 let (start, end) = self.calculate_bounds(range);
167 Buf {
168 layout: BufLayout::Slice {
169 ptr: self.as_ptr() as *mut u8,
170 len: self.len(),
171 },
172 start,
173 end,
174 }
175 }
176
177 unsafe fn recover_from_slice(buf: Buf) -> Self {
178 match buf.layout {
179 BufLayout::Slice { ptr, len } => core::slice::from_raw_parts_mut(ptr as *mut u8, len),
180 _ => unreachable!(),
181 }
182 }
183}
184
185#[cfg(not(feature = "completion-based"))]
186impl IoBufMut for &mut [u8] {
187 fn as_mut_ptr(&mut self) -> *mut u8 {
188 <[u8]>::as_mut_ptr(self)
189 }
190
191 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
192 let (start, end) = self.calculate_bounds(range);
193 BufMut {
194 layout: BufMutLayout::Slice {
195 ptr: self.as_mut_ptr(),
196 len: self.len(),
197 },
198 start,
199 end,
200 }
201 }
202
203 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
204 match buf.layout {
205 BufMutLayout::Slice { ptr, len } => core::slice::from_raw_parts_mut(ptr, len),
206 _ => unreachable!(),
207 }
208 }
209}
210
211#[cfg(feature = "completion-based")]
212impl IoBuf for &'static [u8] {
213 fn as_ptr(&self) -> *const u8 {
214 (*self).as_ptr()
215 }
216
217 fn bytes_init(&self) -> usize {
218 self.len()
219 }
220
221 #[cfg(feature = "bytes")]
222 fn as_bytes(&self) -> bytes::Bytes {
223 bytes::Bytes::from_static(self)
224 }
225
226 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
227 let (start, end) = self.calculate_bounds(range);
228 Buf {
229 layout: BufLayout::Slice {
230 ptr: self.as_ptr() as *mut u8,
231 len: self.len(),
232 },
233 start,
234 end,
235 }
236 }
237
238 unsafe fn recover_from_slice(buf: Buf) -> Self {
239 match buf.layout {
240 BufLayout::Slice { ptr, len } => core::slice::from_raw_parts(ptr, len),
241 _ => unreachable!(),
242 }
243 }
244}
245
246#[cfg(feature = "bytes")]
247impl IoBuf for bytes::Bytes {
248 fn as_ptr(&self) -> *const u8 {
249 <[u8]>::as_ptr(self)
250 }
251
252 fn bytes_init(&self) -> usize {
253 self.len()
254 }
255 fn as_bytes(&self) -> bytes::Bytes {
256 self.clone()
257 }
258
259 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
260 let start = match range.start_bound() {
261 Bound::Included(&start) => start,
262 Bound::Excluded(&start) => start + 1,
263 Bound::Unbounded => 0,
264 };
265 let end = match range.end_bound() {
266 Bound::Included(&end) => end + 1,
267 Bound::Excluded(&end) => end,
268 Bound::Unbounded => self.len(),
269 };
270 Buf {
271 layout: BufLayout::Bytes(self),
272 start,
273 end,
274 }
275 }
276
277 unsafe fn recover_from_slice(buf: Buf) -> Self {
278 match buf.layout {
279 BufLayout::Bytes(bytes) => bytes,
280 _ => unreachable!(),
281 }
282 }
283}
284
285#[cfg(feature = "bytes")]
286impl IoBuf for bytes::BytesMut {
287 fn as_ptr(&self) -> *const u8 {
288 <[u8]>::as_ptr(self)
289 }
290
291 fn bytes_init(&self) -> usize {
292 self.len()
293 }
294
295 fn as_bytes(&self) -> bytes::Bytes {
296 self.clone().freeze()
297 }
298
299 unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
300 let start = match range.start_bound() {
301 Bound::Included(&start) => start,
302 Bound::Excluded(&start) => start + 1,
303 Bound::Unbounded => 0,
304 };
305 let end = match range.end_bound() {
306 Bound::Included(&end) => end + 1,
307 Bound::Excluded(&end) => end,
308 Bound::Unbounded => self.len(),
309 };
310 Buf {
311 layout: BufLayout::BytesMut(self),
312 start,
313 end,
314 }
315 }
316
317 unsafe fn recover_from_slice(buf: Buf) -> Self {
318 match buf.layout {
319 BufLayout::BytesMut(bytes) => bytes,
320 _ => unreachable!(),
321 }
322 }
323}
324
325#[cfg(feature = "bytes")]
326impl IoBufMut for bytes::BytesMut {
327 fn as_mut_ptr(&mut self) -> *mut u8 {
328 <[u8]>::as_mut_ptr(self)
329 }
330
331 unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
332 let start = match range.start_bound() {
333 Bound::Included(&start) => start,
334 Bound::Excluded(&start) => start + 1,
335 Bound::Unbounded => 0,
336 };
337 let end = match range.end_bound() {
338 Bound::Included(&end) => end + 1,
339 Bound::Excluded(&end) => end,
340 Bound::Unbounded => self.len(),
341 };
342 BufMut {
343 layout: BufMutLayout::BytesMut(self),
344 start,
345 end,
346 }
347 }
348
349 unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
350 match buf.layout {
351 BufMutLayout::BytesMut(bytes) => bytes,
352 _ => unreachable!(),
353 }
354 }
355}