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}