1#[cfg(feature = "alloc")]
4use alloc::alloc::{Layout, alloc, dealloc};
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7use core::borrow::Borrow;
8use core::cmp::Ordering;
9use core::fmt::{self, Debug, Formatter};
10use core::hash::{Hash, Hasher};
11use core::ops::Deref;
12use core::ptr;
13
14use crate::value::{TypeTag, Value};
15
16#[repr(C, align(8))]
18struct BytesHeader {
19 len: usize,
21 }
23
24#[repr(transparent)]
29#[derive(Clone)]
30pub struct VBytes(pub(crate) Value);
31
32impl VBytes {
33 fn layout(len: usize) -> Layout {
34 Layout::new::<BytesHeader>()
35 .extend(Layout::array::<u8>(len).unwrap())
36 .unwrap()
37 .0
38 .pad_to_align()
39 }
40
41 #[cfg(feature = "alloc")]
42 fn alloc(data: &[u8]) -> *mut BytesHeader {
43 unsafe {
44 let layout = Self::layout(data.len());
45 let ptr = alloc(layout).cast::<BytesHeader>();
46 (*ptr).len = data.len();
47
48 let data_ptr = ptr.add(1).cast::<u8>();
50 ptr::copy_nonoverlapping(data.as_ptr(), data_ptr, data.len());
51
52 ptr
53 }
54 }
55
56 #[cfg(feature = "alloc")]
57 fn dealloc_ptr(ptr: *mut BytesHeader) {
58 unsafe {
59 let len = (*ptr).len;
60 let layout = Self::layout(len);
61 dealloc(ptr.cast::<u8>(), layout);
62 }
63 }
64
65 fn header(&self) -> &BytesHeader {
66 unsafe { &*(self.0.heap_ptr() as *const BytesHeader) }
67 }
68
69 fn data_ptr(&self) -> *const u8 {
70 unsafe { (self.0.heap_ptr() as *const BytesHeader).add(1).cast() }
73 }
74
75 #[cfg(feature = "alloc")]
77 #[must_use]
78 pub fn new(data: &[u8]) -> Self {
79 if data.is_empty() {
80 return Self::empty();
81 }
82 unsafe {
83 let ptr = Self::alloc(data);
84 VBytes(Value::new_ptr(ptr.cast(), TypeTag::BytesOrFalse))
85 }
86 }
87
88 #[cfg(feature = "alloc")]
90 #[must_use]
91 pub fn empty() -> Self {
92 unsafe {
93 let layout = Self::layout(0);
94 let ptr = alloc(layout).cast::<BytesHeader>();
95 (*ptr).len = 0;
96 VBytes(Value::new_ptr(ptr.cast(), TypeTag::BytesOrFalse))
97 }
98 }
99
100 #[must_use]
102 pub fn len(&self) -> usize {
103 self.header().len
104 }
105
106 #[must_use]
108 pub fn is_empty(&self) -> bool {
109 self.len() == 0
110 }
111
112 #[must_use]
114 pub fn as_slice(&self) -> &[u8] {
115 unsafe { core::slice::from_raw_parts(self.data_ptr(), self.len()) }
116 }
117
118 pub(crate) fn clone_impl(&self) -> Value {
119 VBytes::new(self.as_slice()).0
120 }
121
122 pub(crate) fn drop_impl(&mut self) {
123 unsafe {
124 Self::dealloc_ptr(self.0.heap_ptr_mut().cast());
125 }
126 }
127}
128
129impl Deref for VBytes {
130 type Target = [u8];
131
132 fn deref(&self) -> &[u8] {
133 self.as_slice()
134 }
135}
136
137impl Borrow<[u8]> for VBytes {
138 fn borrow(&self) -> &[u8] {
139 self.as_slice()
140 }
141}
142
143impl AsRef<[u8]> for VBytes {
144 fn as_ref(&self) -> &[u8] {
145 self.as_slice()
146 }
147}
148
149impl PartialEq for VBytes {
150 fn eq(&self, other: &Self) -> bool {
151 self.as_slice() == other.as_slice()
152 }
153}
154
155impl Eq for VBytes {}
156
157impl PartialOrd for VBytes {
158 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
159 Some(self.cmp(other))
160 }
161}
162
163impl Ord for VBytes {
164 fn cmp(&self, other: &Self) -> Ordering {
165 self.as_slice().cmp(other.as_slice())
166 }
167}
168
169impl Hash for VBytes {
170 fn hash<H: Hasher>(&self, state: &mut H) {
171 self.as_slice().hash(state);
172 }
173}
174
175impl Debug for VBytes {
176 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177 write!(f, "b\"")?;
179 for byte in self.as_slice() {
180 write!(f, "\\x{byte:02x}")?;
181 }
182 write!(f, "\"")
183 }
184}
185
186impl Default for VBytes {
187 fn default() -> Self {
188 Self::empty()
189 }
190}
191
192impl PartialEq<[u8]> for VBytes {
195 fn eq(&self, other: &[u8]) -> bool {
196 self.as_slice() == other
197 }
198}
199
200impl PartialEq<VBytes> for [u8] {
201 fn eq(&self, other: &VBytes) -> bool {
202 self == other.as_slice()
203 }
204}
205
206impl PartialEq<&[u8]> for VBytes {
207 fn eq(&self, other: &&[u8]) -> bool {
208 self.as_slice() == *other
209 }
210}
211
212#[cfg(feature = "alloc")]
213impl PartialEq<Vec<u8>> for VBytes {
214 fn eq(&self, other: &Vec<u8>) -> bool {
215 self.as_slice() == other.as_slice()
216 }
217}
218
219#[cfg(feature = "alloc")]
220impl PartialEq<VBytes> for Vec<u8> {
221 fn eq(&self, other: &VBytes) -> bool {
222 self.as_slice() == other.as_slice()
223 }
224}
225
226#[cfg(feature = "alloc")]
229impl From<&[u8]> for VBytes {
230 fn from(data: &[u8]) -> Self {
231 Self::new(data)
232 }
233}
234
235#[cfg(feature = "alloc")]
236impl From<Vec<u8>> for VBytes {
237 fn from(data: Vec<u8>) -> Self {
238 Self::new(&data)
239 }
240}
241
242#[cfg(feature = "alloc")]
243impl From<&Vec<u8>> for VBytes {
244 fn from(data: &Vec<u8>) -> Self {
245 Self::new(data)
246 }
247}
248
249#[cfg(feature = "alloc")]
250impl From<VBytes> for Vec<u8> {
251 fn from(b: VBytes) -> Self {
252 b.as_slice().to_vec()
253 }
254}
255
256impl AsRef<Value> for VBytes {
259 fn as_ref(&self) -> &Value {
260 &self.0
261 }
262}
263
264impl AsMut<Value> for VBytes {
265 fn as_mut(&mut self) -> &mut Value {
266 &mut self.0
267 }
268}
269
270impl From<VBytes> for Value {
271 fn from(b: VBytes) -> Self {
272 b.0
273 }
274}
275
276impl VBytes {
277 #[inline]
279 pub fn into_value(self) -> Value {
280 self.0
281 }
282}
283
284#[cfg(feature = "alloc")]
285impl From<&[u8]> for Value {
286 fn from(data: &[u8]) -> Self {
287 VBytes::new(data).0
288 }
289}
290
291#[cfg(feature = "alloc")]
292impl From<Vec<u8>> for Value {
293 fn from(data: Vec<u8>) -> Self {
294 VBytes::new(&data).0
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301
302 #[test]
303 fn test_new() {
304 let b = VBytes::new(&[1, 2, 3, 4, 5]);
305 assert_eq!(b.as_slice(), &[1, 2, 3, 4, 5]);
306 assert_eq!(b.len(), 5);
307 assert!(!b.is_empty());
308 }
309
310 #[test]
311 fn test_empty() {
312 let b = VBytes::empty();
313 assert_eq!(b.as_slice(), &[] as &[u8]);
314 assert_eq!(b.len(), 0);
315 assert!(b.is_empty());
316 }
317
318 #[test]
319 fn test_equality() {
320 let a = VBytes::new(&[1, 2, 3]);
321 let b = VBytes::new(&[1, 2, 3]);
322 let c = VBytes::new(&[4, 5, 6]);
323
324 assert_eq!(a, b);
325 assert_ne!(a, c);
326 assert_eq!(a, [1, 2, 3].as_slice());
327 }
328
329 #[test]
330 fn test_clone() {
331 let a = VBytes::new(&[0xDE, 0xAD, 0xBE, 0xEF]);
332 let b = a.clone();
333 assert_eq!(a, b);
334 }
335
336 #[test]
337 fn test_ordering() {
338 let a = VBytes::new(&[1, 2, 3]);
339 let b = VBytes::new(&[1, 2, 4]);
340 assert!(a < b);
341 }
342
343 #[test]
344 fn test_debug() {
345 let b = VBytes::new(&[0xDE, 0xAD]);
346 let s = format!("{b:?}");
347 assert_eq!(s, "b\"\\xde\\xad\"");
348 }
349}