Skip to main content

jasn_core/value/
binary.rs

1use std::{
2    borrow::Borrow,
3    ops::{Deref, DerefMut},
4};
5
6/// A wrapper for [`Vec<u8>`]... at least until Rust supports specialization.
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
8pub struct Binary(pub Vec<u8>);
9
10impl Binary {
11    /// Creates a new empty `Binary`.
12    pub fn new() -> Self {
13        Binary(Vec::new())
14    }
15
16    /// Creates a new `Binary` with the specified capacity.
17    pub fn with_capacity(capacity: usize) -> Self {
18        Binary(Vec::with_capacity(capacity))
19    }
20
21    /// Returns the number of bytes in the binary data.
22    pub fn len(&self) -> usize {
23        self.0.len()
24    }
25
26    /// Returns `true` if the binary data contains no bytes.
27    pub fn is_empty(&self) -> bool {
28        self.0.is_empty()
29    }
30
31    /// Returns the capacity of the underlying vector.
32    pub fn capacity(&self) -> usize {
33        self.0.capacity()
34    }
35
36    /// Reserves capacity for at least `additional` more bytes.
37    pub fn reserve(&mut self, additional: usize) {
38        self.0.reserve(additional);
39    }
40
41    /// Appends a byte to the end of the binary data.
42    pub fn push(&mut self, byte: u8) {
43        self.0.push(byte);
44    }
45
46    /// Removes and returns the last byte, or `None` if empty.
47    pub fn pop(&mut self) -> Option<u8> {
48        self.0.pop()
49    }
50
51    /// Clears the binary data, removing all bytes.
52    pub fn clear(&mut self) {
53        self.0.clear();
54    }
55
56    /// Truncates the binary data to the specified length.
57    pub fn truncate(&mut self, len: usize) {
58        self.0.truncate(len);
59    }
60
61    /// Appends all bytes from a slice to the binary data.
62    pub fn extend_from_slice(&mut self, slice: &[u8]) {
63        self.0.extend_from_slice(slice);
64    }
65}
66
67impl From<Vec<u8>> for Binary {
68    fn from(v: Vec<u8>) -> Self {
69        Binary(v)
70    }
71}
72
73impl From<Binary> for Vec<u8> {
74    fn from(binary: Binary) -> Self {
75        binary.0
76    }
77}
78
79impl From<&[u8]> for Binary {
80    fn from(slice: &[u8]) -> Self {
81        Binary(slice.to_vec())
82    }
83}
84
85impl<const N: usize> From<&[u8; N]> for Binary {
86    fn from(arr: &[u8; N]) -> Self {
87        Binary(arr.to_vec())
88    }
89}
90
91impl<const N: usize> From<[u8; N]> for Binary {
92    fn from(arr: [u8; N]) -> Self {
93        Binary(arr.to_vec())
94    }
95}
96
97impl AsRef<[u8]> for Binary {
98    fn as_ref(&self) -> &[u8] {
99        &self.0
100    }
101}
102
103impl AsMut<[u8]> for Binary {
104    fn as_mut(&mut self) -> &mut [u8] {
105        &mut self.0
106    }
107}
108
109impl Deref for Binary {
110    type Target = [u8];
111
112    fn deref(&self) -> &Self::Target {
113        &self.0
114    }
115}
116
117impl DerefMut for Binary {
118    fn deref_mut(&mut self) -> &mut Self::Target {
119        &mut self.0
120    }
121}
122
123impl Borrow<[u8]> for Binary {
124    fn borrow(&self) -> &[u8] {
125        &self.0
126    }
127}
128
129impl PartialEq<[u8]> for Binary {
130    fn eq(&self, other: &[u8]) -> bool {
131        self.0 == other
132    }
133}
134
135impl PartialEq<&[u8]> for Binary {
136    fn eq(&self, other: &&[u8]) -> bool {
137        &self.0 == other
138    }
139}
140
141impl PartialEq<Vec<u8>> for Binary {
142    fn eq(&self, other: &Vec<u8>) -> bool {
143        &self.0 == other
144    }
145}
146
147impl<const N: usize> PartialEq<[u8; N]> for Binary {
148    fn eq(&self, other: &[u8; N]) -> bool {
149        self.0 == other
150    }
151}
152
153impl<const N: usize> PartialEq<&[u8; N]> for Binary {
154    fn eq(&self, other: &&[u8; N]) -> bool {
155        &self.0 == other
156    }
157}
158
159impl FromIterator<u8> for Binary {
160    fn from_iter<I: IntoIterator<Item = u8>>(iter: I) -> Self {
161        Binary(iter.into_iter().collect())
162    }
163}
164
165impl Extend<u8> for Binary {
166    fn extend<I: IntoIterator<Item = u8>>(&mut self, iter: I) {
167        self.0.extend(iter);
168    }
169}
170
171impl IntoIterator for Binary {
172    type Item = u8;
173    type IntoIter = std::vec::IntoIter<u8>;
174
175    fn into_iter(self) -> Self::IntoIter {
176        self.0.into_iter()
177    }
178}
179
180impl<'a> IntoIterator for &'a Binary {
181    type Item = &'a u8;
182    type IntoIter = std::slice::Iter<'a, u8>;
183
184    fn into_iter(self) -> Self::IntoIter {
185        self.0.iter()
186    }
187}
188
189impl<'a> IntoIterator for &'a mut Binary {
190    type Item = &'a mut u8;
191    type IntoIter = std::slice::IterMut<'a, u8>;
192
193    fn into_iter(self) -> Self::IntoIter {
194        self.0.iter_mut()
195    }
196}
197
198#[cfg(test)]
199mod tests {
200    use rstest::rstest;
201
202    use super::*;
203
204    #[rstest]
205    #[case(Binary::from(vec![1u8, 2, 3]), vec![1, 2, 3])]
206    #[case(Binary::from(b"hello"), b"hello".to_vec())]
207    #[case(Binary::from(b"world"), b"world".to_vec())]
208    #[case(Binary::from([1u8, 2, 3]), vec![1, 2, 3])]
209    fn test_binary_from_conversions(#[case] binary: Binary, #[case] expected: Vec<u8>) {
210        assert_eq!(binary, Binary(expected));
211    }
212
213    #[test]
214    fn test_binary_conversions() {
215        // Binary from &[u8] (slice reference)
216        let bytes: &[u8] = b"slice";
217        let binary = Binary::from(bytes);
218        assert_eq!(binary, Binary(b"slice".to_vec()));
219
220        // Binary to Vec<u8>
221        let binary = Binary(vec![1, 2, 3]);
222        let vec: Vec<u8> = binary.clone().into();
223        assert_eq!(vec, vec![1, 2, 3]);
224
225        // Binary AsRef<[u8]>
226        let binary = Binary(vec![4, 5, 6]);
227        let slice: &[u8] = binary.as_ref();
228        assert_eq!(slice, &[4, 5, 6]);
229
230        // Binary Deref to [u8]
231        let binary = Binary(vec![7, 8, 9]);
232        assert_eq!(&*binary, &[7, 8, 9]);
233        assert_eq!(binary.len(), 3);
234        assert_eq!(binary[0], 7);
235
236        // Binary AsMut<[u8]>
237        let mut binary = Binary(vec![1, 2, 3]);
238        let slice_mut: &mut [u8] = binary.as_mut();
239        slice_mut[0] = 99;
240        assert_eq!(binary.as_ref(), &[99, 2, 3]);
241
242        // Binary DerefMut to [u8]
243        let mut binary = Binary(vec![4, 5, 6]);
244        binary[1] = 88;
245        assert_eq!(&*binary, &[4, 88, 6]);
246    }
247
248    #[test]
249    fn test_binary_construction() {
250        // Binary::new()
251        let binary = Binary::new();
252        assert_eq!(binary.len(), 0);
253        assert!(binary.is_empty());
254
255        // Binary::with_capacity()
256        let binary = Binary::with_capacity(10);
257        assert_eq!(binary.len(), 0);
258        assert!(binary.capacity() >= 10);
259
260        // Binary::default()
261        let binary = Binary::default();
262        assert_eq!(binary, Binary::new());
263    }
264
265    #[rstest]
266    #[case(Binary::new(), 0, true)]
267    #[case(Binary::from(vec![1, 2, 3]), 3, false)]
268    fn test_binary_length_check(
269        #[case] binary: Binary,
270        #[case] len: usize,
271        #[case] is_empty: bool,
272    ) {
273        assert_eq!(binary.len(), len);
274        assert_eq!(binary.is_empty(), is_empty);
275    }
276
277    #[test]
278    fn test_binary_methods() {
279        let mut binary = Binary::new();
280
281        // push
282        binary.push(1);
283        binary.push(2);
284        binary.push(3);
285        assert_eq!(binary.len(), 3);
286        assert_eq!(&*binary, &[1, 2, 3]);
287
288        // pop
289        assert_eq!(binary.pop(), Some(3));
290        assert_eq!(binary.len(), 2);
291        assert_eq!(&*binary, &[1, 2]);
292
293        // extend_from_slice
294        binary.extend_from_slice(&[4, 5, 6]);
295        assert_eq!(&*binary, &[1, 2, 4, 5, 6]);
296
297        // truncate
298        binary.truncate(3);
299        assert_eq!(binary.len(), 3);
300        assert_eq!(&*binary, &[1, 2, 4]);
301
302        // clear
303        binary.clear();
304        assert_eq!(binary.len(), 0);
305        assert!(binary.is_empty());
306
307        // pop on empty
308        assert_eq!(binary.pop(), None);
309    }
310
311    #[test]
312    fn test_binary_iterators() {
313        let binary = Binary::from(vec![1u8, 2, 3]);
314
315        // IntoIterator for Binary (consuming)
316        let vec: Vec<u8> = binary.clone().into_iter().collect();
317        assert_eq!(vec, vec![1, 2, 3]);
318
319        // IntoIterator for &Binary
320        let sum: u8 = (&binary).into_iter().sum();
321        assert_eq!(sum, 6);
322
323        // IntoIterator for &mut Binary
324        let mut binary = Binary::from(vec![1u8, 2, 3]);
325        for byte in &mut binary {
326            *byte *= 2;
327        }
328        assert_eq!(&*binary, &[2, 4, 6]);
329
330        // FromIterator<u8>
331        let binary: Binary = vec![7u8, 8, 9].into_iter().collect();
332        assert_eq!(&*binary, &[7, 8, 9]);
333
334        // Extend<u8>
335        let mut binary = Binary::from(vec![1u8, 2]);
336        binary.extend(vec![3, 4, 5]);
337        assert_eq!(&*binary, &[1, 2, 3, 4, 5]);
338    }
339
340    #[rstest]
341    #[case(Binary::from(vec![1u8, 2, 3]), &[1u8, 2, 3] as &[u8], true)]
342    #[case(Binary::from(vec![1u8, 2, 3]), &[1u8, 2] as &[u8], false)]
343    #[case(Binary::from(b"hello"), b"hello" as &[u8], true)]
344    #[case(Binary::from(b"hello"), b"world" as &[u8], false)]
345    fn test_binary_slice_eq(#[case] binary: Binary, #[case] slice: &[u8], #[case] should_eq: bool) {
346        if should_eq {
347            assert_eq!(binary, slice);
348        } else {
349            assert_ne!(binary, slice);
350        }
351    }
352
353    #[rstest]
354    #[case(Binary::from(vec![1u8, 2, 3]), vec![1u8, 2, 3], true)]
355    #[case(Binary::from(vec![1u8, 2, 3]), vec![1u8, 2], false)]
356    fn test_binary_vec_eq(#[case] binary: Binary, #[case] vec: Vec<u8>, #[case] should_eq: bool) {
357        if should_eq {
358            assert_eq!(binary, vec);
359        } else {
360            assert_ne!(binary, vec);
361        }
362    }
363
364    #[test]
365    fn test_binary_partial_eq() {
366        let binary = Binary::from(vec![1u8, 2, 3]);
367
368        // PartialEq<[u8; N]>
369        assert_eq!(binary, [1u8, 2, 3]);
370        assert_ne!(binary, [1u8, 2, 3, 4]);
371
372        // PartialEq<&[u8; N]>
373        let arr: &[u8; 3] = &[1, 2, 3];
374        assert_eq!(binary, arr);
375    }
376
377    #[test]
378    fn test_binary_borrow() {
379        use std::collections::HashMap;
380
381        let mut map: HashMap<Binary, &str> = HashMap::new();
382        let key = Binary::from(vec![1u8, 2, 3]);
383        map.insert(key.clone(), "value");
384
385        // Can lookup with &[u8] thanks to Borrow<[u8]>
386        let lookup: &[u8] = &[1, 2, 3];
387        assert_eq!(map.get(lookup), Some(&"value"));
388
389        // Can lookup with byte literal
390        let key2 = Binary::from(b"hello");
391        map.insert(key2.clone(), "world");
392        assert_eq!(map.get(b"hello".as_slice()), Some(&"world"));
393    }
394}