fusio_core/buf/
slice.rs

1#[cfg(feature = "alloc")]
2use alloc::vec::Vec;
3use core::ops::{Bound, RangeBounds};
4
5use super::{IoBuf, IoBufMut};
6
7pub struct Buf {
8    pub(super) layout: BufLayout,
9    pub(super) start: usize,
10    pub(super) end: usize,
11}
12
13#[cfg(not(feature = "no-send"))]
14unsafe impl Send for Buf {}
15
16pub(super) enum BufLayout {
17    Slice {
18        ptr: *const u8,
19        len: usize,
20    },
21    #[cfg(feature = "alloc")]
22    Vec(Vec<u8>),
23    #[cfg(feature = "bytes")]
24    Bytes(bytes::Bytes),
25    #[cfg(feature = "bytes")]
26    BytesMut(bytes::BytesMut),
27}
28
29impl IoBuf for Buf {
30    fn as_ptr(&self) -> *const u8 {
31        match &self.layout {
32            BufLayout::Slice { ptr, .. } => unsafe { (*ptr).add(self.start) },
33            #[cfg(feature = "alloc")]
34            BufLayout::Vec(vec) => vec[self.start..].as_ptr(),
35            #[cfg(feature = "bytes")]
36            BufLayout::Bytes(bytes) => bytes[self.start..].as_ptr(),
37            #[cfg(feature = "bytes")]
38            BufLayout::BytesMut(bytes) => bytes[self.start..].as_ptr(),
39        }
40    }
41
42    fn bytes_init(&self) -> usize {
43        match &self.layout {
44            BufLayout::Slice { len, .. } => *len - self.start,
45            #[cfg(feature = "alloc")]
46            BufLayout::Vec(vec) => vec.len() - self.start,
47            #[cfg(feature = "bytes")]
48            BufLayout::Bytes(bytes) => bytes.len() - self.start,
49            #[cfg(feature = "bytes")]
50            BufLayout::BytesMut(bytes) => bytes.len() - self.start,
51        }
52    }
53
54    #[cfg(feature = "bytes")]
55    fn as_bytes(&self) -> bytes::Bytes {
56        match &self.layout {
57            BufLayout::Slice { ptr, .. } => bytes::Bytes::copy_from_slice(unsafe {
58                core::slice::from_raw_parts((*ptr).add(self.start), self.end - self.start)
59            }),
60            BufLayout::Vec(vec) => bytes::Bytes::copy_from_slice(&vec[self.start..self.end]),
61            #[cfg(feature = "bytes")]
62            BufLayout::Bytes(bytes) => bytes.slice(self.start..self.end),
63            #[cfg(feature = "bytes")]
64            BufLayout::BytesMut(bytes) => bytes.clone().freeze().slice(self.start..self.end),
65        }
66    }
67
68    unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
69        let start = match range.start_bound() {
70            Bound::Included(&start) => start,
71            Bound::Excluded(&start) => start + 1,
72            Bound::Unbounded => self.start,
73        };
74        let end = match range.end_bound() {
75            Bound::Included(&end) => end + 1,
76            Bound::Excluded(&end) => end,
77            Bound::Unbounded => self.end,
78        };
79        Buf {
80            layout: self.layout,
81            start,
82            end,
83        }
84    }
85
86    unsafe fn recover_from_slice(buf: Buf) -> Self {
87        buf
88    }
89}
90
91pub struct BufMut {
92    pub(super) layout: BufMutLayout,
93    pub(super) start: usize,
94    pub(super) end: usize,
95}
96
97#[cfg(not(feature = "no-send"))]
98unsafe impl Send for BufMut {}
99
100pub(super) enum BufMutLayout {
101    #[allow(unused)]
102    Slice { ptr: *mut u8, len: usize },
103    #[cfg(feature = "alloc")]
104    Vec(Vec<u8>),
105    #[cfg(feature = "bytes")]
106    BytesMut(bytes::BytesMut),
107}
108
109impl IoBuf for BufMut {
110    fn as_ptr(&self) -> *const u8 {
111        match &self.layout {
112            BufMutLayout::Slice { ptr, .. } => unsafe { (*ptr).add(self.start) },
113            #[cfg(feature = "alloc")]
114            BufMutLayout::Vec(vec) => vec[self.start..].as_ptr(),
115            #[cfg(feature = "bytes")]
116            BufMutLayout::BytesMut(bytes) => bytes[self.start..].as_ptr(),
117        }
118    }
119
120    fn bytes_init(&self) -> usize {
121        match &self.layout {
122            BufMutLayout::Slice { len, .. } => *len - self.start,
123            #[cfg(feature = "alloc")]
124            BufMutLayout::Vec(vec) => vec.len() - self.start,
125            #[cfg(feature = "bytes")]
126            BufMutLayout::BytesMut(bytes) => bytes.len() - self.start,
127        }
128    }
129
130    #[cfg(feature = "bytes")]
131    fn as_bytes(&self) -> bytes::Bytes {
132        match &self.layout {
133            BufMutLayout::Slice { ptr, .. } => bytes::Bytes::copy_from_slice(unsafe {
134                core::slice::from_raw_parts((*ptr).add(self.start), self.end - self.start)
135            }),
136            BufMutLayout::Vec(vec) => bytes::Bytes::copy_from_slice(&vec[self.start..self.end]),
137            #[cfg(feature = "bytes")]
138            BufMutLayout::BytesMut(bytes) => bytes.clone().freeze().slice(self.start..self.end),
139        }
140    }
141
142    unsafe fn slice_unchecked(self, range: impl RangeBounds<usize>) -> Buf {
143        let start = match range.start_bound() {
144            Bound::Included(&start) => start,
145            Bound::Excluded(&start) => start + 1,
146            Bound::Unbounded => self.start,
147        };
148        let end = match range.end_bound() {
149            Bound::Included(&end) => end + 1,
150            Bound::Excluded(&end) => end,
151            Bound::Unbounded => self.end,
152        };
153        match self.layout {
154            BufMutLayout::Slice { ptr, len } => Buf {
155                layout: BufLayout::Slice {
156                    ptr: ptr as *const u8,
157                    len,
158                },
159                start,
160                end,
161            },
162            #[cfg(feature = "alloc")]
163            BufMutLayout::Vec(vec) => Buf {
164                layout: BufLayout::Vec(vec),
165                start,
166                end,
167            },
168            #[cfg(feature = "bytes")]
169            BufMutLayout::BytesMut(bytes) => Buf {
170                layout: BufLayout::BytesMut(bytes),
171                start,
172                end,
173            },
174        }
175    }
176
177    unsafe fn recover_from_slice(buf: Buf) -> Self {
178        match buf.layout {
179            BufLayout::Slice { ptr, len } => BufMut {
180                layout: BufMutLayout::Slice {
181                    ptr: ptr as *mut u8,
182                    len,
183                },
184                start: buf.start,
185                end: buf.end,
186            },
187            #[cfg(feature = "alloc")]
188            BufLayout::Vec(vec) => BufMut {
189                layout: BufMutLayout::Vec(vec),
190                start: buf.start,
191                end: buf.end,
192            },
193            #[cfg(feature = "bytes")]
194            BufLayout::Bytes(_) => unreachable!(),
195            #[cfg(feature = "bytes")]
196            BufLayout::BytesMut(bytes) => BufMut {
197                layout: BufMutLayout::BytesMut(bytes),
198                start: buf.start,
199                end: buf.end,
200            },
201        }
202    }
203}
204
205impl IoBufMut for BufMut {
206    fn as_mut_ptr(&mut self) -> *mut u8 {
207        match &mut self.layout {
208            BufMutLayout::Slice { ptr, .. } => unsafe { (*ptr).add(self.start) },
209            #[cfg(feature = "alloc")]
210            BufMutLayout::Vec(vec) => vec[self.start..].as_mut_ptr(),
211            #[cfg(feature = "bytes")]
212            BufMutLayout::BytesMut(bytes) => bytes[self.start..].as_mut_ptr(),
213        }
214    }
215
216    unsafe fn slice_mut_unchecked(self, range: impl RangeBounds<usize>) -> BufMut {
217        let start = match range.start_bound() {
218            Bound::Included(&start) => start,
219            Bound::Excluded(&start) => start + 1,
220            Bound::Unbounded => self.start,
221        };
222        let end = match range.end_bound() {
223            Bound::Included(&end) => end + 1,
224            Bound::Excluded(&end) => end,
225            Bound::Unbounded => self.end,
226        };
227        BufMut {
228            layout: self.layout,
229            start,
230            end,
231        }
232    }
233
234    unsafe fn recover_from_slice_mut(buf: BufMut) -> Self {
235        buf
236    }
237}