dharitri_chain_core/types/
boxed_bytes.rs1use alloc::{
2 alloc::{alloc, realloc, Layout},
3 boxed::Box,
4 vec,
5 vec::Vec,
6};
7
8use crate::codec::*;
9
10#[derive(Clone, PartialEq, Eq, Debug)]
17pub struct BoxedBytes(Box<[u8]>);
18
19impl BoxedBytes {
20 pub fn empty() -> Self {
21 BoxedBytes(Box::from([0u8; 0]))
22 }
23
24 pub fn zeros(len: usize) -> Self {
25 let bytes_box = Box::from(vec![0u8; len]);
26 BoxedBytes(bytes_box)
27 }
28
29 #[inline]
30 pub fn as_ptr(&self) -> *const u8 {
31 self.0.as_ptr()
32 }
33
34 #[inline]
35 pub fn as_mut_ptr(&mut self) -> *mut u8 {
36 self.0.as_mut_ptr()
37 }
38
39 #[inline]
40 pub fn len(&self) -> usize {
41 self.0.len()
42 }
43
44 #[inline]
45 pub fn is_empty(&self) -> bool {
46 self.0.is_empty()
47 }
48
49 #[inline]
50 pub fn into_box(self) -> Box<[u8]> {
51 self.0
52 }
53
54 #[inline]
55 pub fn into_vec(self) -> Vec<u8> {
56 self.0.into_vec()
57 }
58
59 #[inline]
60 pub fn as_slice(&self) -> &[u8] {
61 &self.0
62 }
63
64 #[inline]
65 pub fn as_mut_slice(&mut self) -> &mut [u8] {
66 &mut self.0
67 }
68
69 pub fn from_concat(slices: &[&[u8]]) -> Self {
71 let mut result_len = 0usize;
72 let mut index = slices.len();
73 while index > 0 {
74 index -= 1;
75 result_len += slices[index].len();
76 }
77 unsafe {
78 let layout = Layout::from_size_align(result_len, core::mem::align_of::<u8>()).unwrap();
79 let result_ptr = alloc(layout);
80 let mut current_index = 0usize;
81 for slice in slices.iter() {
82 core::ptr::copy_nonoverlapping(
83 slice.as_ptr(),
84 result_ptr.add(current_index),
85 slice.len(),
86 );
87 current_index += slice.len();
88 }
89 let bytes_box = Box::from_raw(core::slice::from_raw_parts_mut(result_ptr, result_len));
90 BoxedBytes(bytes_box)
91 }
92 }
93
94 pub fn split(self, at: usize) -> (BoxedBytes, BoxedBytes) {
97 if at >= self.len() {
98 (self, BoxedBytes::empty())
99 } else {
100 let other_len = self.len() - at;
101 unsafe {
102 let self_layout =
104 Layout::from_size_align(self.len(), core::mem::align_of::<u8>()).unwrap();
105 let self_ptr = Box::into_raw(self.0) as *mut u8;
106
107 let other_layout =
109 Layout::from_size_align(other_len, core::mem::align_of::<u8>()).unwrap();
110 let other_ptr = alloc(other_layout);
111 core::ptr::copy_nonoverlapping(self_ptr.add(at), other_ptr, other_len);
112
113 let realloc_ptr = realloc(self_ptr, self_layout, at);
116
117 let bytes_box_1 = Box::from_raw(core::slice::from_raw_parts_mut(realloc_ptr, at));
119 let bytes_box_2 =
120 Box::from_raw(core::slice::from_raw_parts_mut(other_ptr, other_len));
121 (BoxedBytes(bytes_box_1), BoxedBytes(bytes_box_2))
122 }
123 }
124 }
125}
126
127impl AsRef<[u8]> for BoxedBytes {
128 #[inline]
129 fn as_ref(&self) -> &[u8] {
130 &self.0
131 }
132}
133
134impl<'a> From<&'a [u8]> for BoxedBytes {
135 #[inline]
136 fn from(byte_slice: &'a [u8]) -> Self {
137 BoxedBytes(Box::from(byte_slice))
138 }
139}
140
141impl From<Box<[u8]>> for BoxedBytes {
142 #[inline]
143 fn from(b: Box<[u8]>) -> Self {
144 BoxedBytes(b)
145 }
146}
147
148impl From<Vec<u8>> for BoxedBytes {
149 #[inline]
150 fn from(v: Vec<u8>) -> Self {
151 BoxedBytes(v.into_boxed_slice())
152 }
153}
154
155impl From<&Vec<u8>> for BoxedBytes {
156 #[inline]
157 fn from(v: &Vec<u8>) -> Self {
158 BoxedBytes::from(v.as_slice())
159 }
160}
161
162impl TopEncodeOutput for &mut BoxedBytes {
164 type NestedBuffer = Vec<u8>;
165
166 fn set_slice_u8(self, bytes: &[u8]) {
167 *self = BoxedBytes::from(bytes);
168 }
169
170 fn start_nested_encode(&self) -> Self::NestedBuffer {
171 Vec::<u8>::new()
172 }
173
174 fn finalize_nested_encode(self, nb: Self::NestedBuffer) {
175 self.set_slice_u8(nb.as_slice());
176 }
177}
178
179impl NestedEncode for BoxedBytes {
180 #[inline]
181 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
182 where
183 O: NestedEncodeOutput,
184 H: EncodeErrorHandler,
185 {
186 self.len().dep_encode_or_handle_err(dest, h)?;
187 dest.write(self.as_ref());
188 Ok(())
189 }
190}
191
192impl TopEncode for BoxedBytes {
193 #[inline]
194 fn top_encode_or_handle_err<O, H>(&self, output: O, _h: H) -> Result<(), H::HandledErr>
195 where
196 O: TopEncodeOutput,
197 H: EncodeErrorHandler,
198 {
199 output.set_slice_u8(self.as_ref());
200 Ok(())
201 }
202}
203
204impl NestedDecode for BoxedBytes {
205 fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
206 where
207 I: NestedDecodeInput,
208 H: DecodeErrorHandler,
209 {
210 let size = usize::dep_decode_or_handle_err(input, h)?;
211 let mut result = BoxedBytes::zeros(size);
212 input.read_into(result.as_mut_slice(), h)?;
213 Ok(result)
214 }
215}
216
217impl TopDecode for BoxedBytes {
218 fn top_decode_or_handle_err<I, H>(input: I, _h: H) -> Result<Self, H::HandledErr>
219 where
220 I: TopDecodeInput,
221 H: DecodeErrorHandler,
222 {
223 Ok(BoxedBytes(input.into_boxed_slice_u8()))
224 }
225}
226
227#[cfg(test)]
230mod tests {
231 use super::*;
232
233 #[test]
234 fn test_concat_1() {
235 let bb = BoxedBytes::from_concat(&[&b"abc"[..], &b"def"[..]]);
236 assert_eq!(bb, BoxedBytes::from(&b"abcdef"[..]));
237 }
238
239 #[test]
240 fn test_concat_2() {
241 let bb = BoxedBytes::from_concat(&[&b"abc"[..], &b""[..], &b"def"[..]]);
242 assert_eq!(bb, BoxedBytes::from(&b"abcdef"[..]));
243 }
244
245 #[test]
246 fn test_concat_empty_1() {
247 let bb = BoxedBytes::from_concat(&[&b""[..], &b""[..], &b""[..]]);
248 assert_eq!(bb, BoxedBytes::from(&b""[..]));
249 }
250
251 #[test]
252 fn test_concat_empty_2() {
253 let bb = BoxedBytes::from_concat(&[]);
254 assert_eq!(bb, BoxedBytes::from(&b""[..]));
255 }
256
257 #[test]
258 fn test_is_empty() {
259 assert!(BoxedBytes::empty().is_empty());
260 }
261
262 #[test]
263 fn test_size_of() {
264 use core::mem::size_of;
265 assert_eq!(size_of::<BoxedBytes>(), 2 * size_of::<usize>());
266 assert_eq!(size_of::<Option<BoxedBytes>>(), 2 * size_of::<usize>());
267 }
268
269 #[test]
270 fn test_split_1() {
271 let (bb1, bb2) = BoxedBytes::from(&b"abcdef"[..]).split(3);
272 assert_eq!(bb1, BoxedBytes::from(&b"abc"[..]));
273 assert_eq!(bb2, BoxedBytes::from(&b"def"[..]));
274 }
275
276 #[test]
277 fn test_split_2() {
278 let (bb1, bb2) = BoxedBytes::from(&b"abcdef"[..]).split(0);
279 assert_eq!(bb1, BoxedBytes::from(&b""[..]));
280 assert_eq!(bb2, BoxedBytes::from(&b"abcdef"[..]));
281 }
282
283 #[test]
284 fn test_split_over() {
285 let (bb1, bb2) = BoxedBytes::from(&b"abcdef"[..]).split(6);
286 assert_eq!(bb1, BoxedBytes::from(&b"abcdef"[..]));
287 assert_eq!(bb2, BoxedBytes::from(&b""[..]));
288
289 let (bb1, bb2) = BoxedBytes::from(&b"abcdef"[..]).split(7);
290 assert_eq!(bb1, BoxedBytes::from(&b"abcdef"[..]));
291 assert_eq!(bb2, BoxedBytes::from(&b""[..]));
292 }
293}