dcbor/
byte_string.rs

1import_stdlib!();
2
3use crate::{ CBOR, Error };
4
5/// Represents a CBOR byte string (major type 2).
6///
7/// `ByteString` is a wrapper around a byte vector, optimized for use in CBOR
8/// encoding and decoding operations. It provides a richer API for working with
9/// byte data in the context of CBOR compared to using raw `Vec<u8>` values.
10///
11/// In dCBOR, byte strings follow the general deterministic encoding rules:
12/// - They must use definite-length encoding
13/// - Their length must be encoded in the shortest possible form
14///
15/// # Use Cases
16///
17/// Byte strings in CBOR are commonly used for:
18/// - Binary data such as images, audio, or other non-text content
19/// - Cryptographic values like hashes, signatures, and public keys
20/// - Embedded CBOR (wrapped with tag 24)
21/// - Other serialized data formats embedded in CBOR
22///
23/// # Examples
24///
25/// ```
26/// use dcbor::prelude::*;
27///
28/// // Creating a byte string from various sources
29/// let bytes1 = ByteString::new(vec![1, 2, 3, 4]);
30/// let bytes2 = ByteString::from([5, 6, 7, 8]);
31/// let bytes3 = ByteString::from(&[9, 10, 11, 12][..]);
32///
33/// // Converting to and from CBOR
34/// let cbor = CBOR::from(bytes1.clone());
35/// assert_eq!(cbor.diagnostic(), "h'01020304'");
36///
37/// // The byte string can be extracted from CBOR
38/// let extracted: ByteString = cbor.try_into().unwrap();
39/// assert_eq!(extracted, bytes1);
40///
41/// // ByteString provides Vec<u8>-like operations
42/// let mut bytes = ByteString::new(vec![1, 2]);
43/// bytes.extend(vec![3, 4]);
44/// assert_eq!(bytes.len(), 4);
45/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
46/// ```
47#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
48pub struct ByteString(Vec<u8>);
49
50impl ByteString {
51    /// Creates a new `ByteString` from any type that can be converted into a byte vector.
52    ///
53    /// This constructor accepts any type that implements `Into<Vec<u8>>`, which includes
54    /// common types like `Vec<u8>`, arrays `[u8; N]`, slices `&[u8]`, and string slices
55    /// `&str` (via the `From<&str>` implementation).
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use dcbor::prelude::*;
61    ///
62    /// // From a vector
63    /// let bytes1 = ByteString::new(vec![1, 2, 3, 4]);
64    ///
65    /// // From a byte array
66    /// let bytes2 = ByteString::new([5, 6, 7, 8]);
67    ///
68    /// // From a byte slice
69    /// let bytes3 = ByteString::new(&[9, 10, 11, 12][..]);
70    ///
71    /// // From a hex string (using an implementation elsewhere)
72    /// let hex = "deadbeef";
73    /// let bytes4 = ByteString::new(hex::decode(hex).unwrap());
74    /// ```
75    pub fn new(data: impl AsRef<[u8]>) -> Self {
76        Self(data.as_ref().to_vec())
77    }
78
79    /// Returns a reference to the underlying byte data.
80    ///
81    /// This method provides access to the raw bytes without cloning them.
82    ///
83    /// # Examples
84    ///
85    /// ```
86    /// use dcbor::prelude::*;
87    ///
88    /// let bytes = ByteString::new([1, 2, 3, 4]);
89    /// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
90    ///
91    /// // You can use standard slice operations on the result
92    /// assert_eq!(bytes.data()[1..3], [2, 3]);
93    /// ```
94    pub fn data(&self) -> &[u8] {
95        &self.0
96    }
97
98    /// Returns the length of the byte string in bytes.
99    ///
100    /// # Examples
101    ///
102    /// ```
103    /// use dcbor::prelude::*;
104    ///
105    /// let empty = ByteString::new(vec![]);
106    /// assert_eq!(empty.len(), 0);
107    ///
108    /// let bytes = ByteString::new([1, 2, 3, 4]);
109    /// assert_eq!(bytes.len(), 4);
110    /// ```
111    pub fn len(&self) -> usize {
112        self.0.len()
113    }
114
115    /// Returns `true` if the byte string contains no bytes.
116    ///
117    /// # Examples
118    ///
119    /// ```
120    /// use dcbor::prelude::*;
121    ///
122    /// let empty = ByteString::new(vec![]);
123    /// assert!(empty.is_empty());
124    ///
125    /// let bytes = ByteString::new([1, 2, 3, 4]);
126    /// assert!(!bytes.is_empty());
127    /// ```
128    pub fn is_empty(&self) -> bool {
129        self.0.is_empty()
130    }
131
132    /// Extends the byte string with additional bytes.
133    ///
134    /// This method appends the bytes from the provided value to the end of
135    /// the existing byte string.
136    ///
137    /// # Examples
138    ///
139    /// ```
140    /// use dcbor::prelude::*;
141    ///
142    /// let mut bytes = ByteString::new([1, 2]);
143    /// bytes.extend([3, 4]);
144    /// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
145    ///
146    /// // You can extend with different types
147    /// bytes.extend(vec![5, 6]);
148    /// assert_eq!(bytes.data(), &[1, 2, 3, 4, 5, 6]);
149    /// ```
150    pub fn extend(&mut self, other: impl AsRef<[u8]>) {
151        self.0.extend(other.as_ref());
152    }
153
154    /// Creates a new vector containing a copy of the byte string's data.
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use dcbor::prelude::*;
160    ///
161    /// let bytes = ByteString::new([1, 2, 3, 4]);
162    /// let vec = bytes.to_vec();
163    /// assert_eq!(vec, vec![1, 2, 3, 4]);
164    ///
165    /// // The returned vector is a clone, so you can modify it independently
166    /// let mut vec2 = bytes.to_vec();
167    /// vec2.push(5);
168    /// assert_eq!(vec2, vec![1, 2, 3, 4, 5]);
169    /// assert_eq!(bytes.data(), &[1, 2, 3, 4]); // original unchanged
170    /// ```
171    pub fn to_vec(&self) -> Vec<u8> {
172        self.0.clone()
173    }
174
175    /// Returns an iterator over the bytes in the byte string.
176    ///
177    /// The iterator yields references to each byte in the byte string.
178    ///
179    /// # Examples
180    ///
181    /// ```
182    /// use dcbor::prelude::*;
183    ///
184    /// let bytes = ByteString::new([1, 2, 3]);
185    /// let mut iter = bytes.iter();
186    ///
187    /// assert_eq!(iter.next(), Some(&1));
188    /// assert_eq!(iter.next(), Some(&2));
189    /// assert_eq!(iter.next(), Some(&3));
190    /// assert_eq!(iter.next(), None);
191    ///
192    /// // You can also use for loops
193    /// let mut sum = 0;
194    /// for byte in bytes.iter() {
195    ///     sum += *byte;
196    /// }
197    /// assert_eq!(sum, 6);
198    /// ```
199    pub fn iter(&self) -> ByteStringIterator<'_> {
200        ByteStringIterator {
201            slice: &self.0,
202            pos: 0,
203        }
204    }
205}
206
207/// Converts a `ByteString` into a `Vec<u8>`.
208///
209/// This allows consuming a byte string and getting ownership of the underlying byte vector.
210///
211/// # Examples
212///
213/// ```
214/// use dcbor::prelude::*;
215///
216/// let bytes = ByteString::new([1, 2, 3, 4]);
217/// let vec: Vec<u8> = bytes.into();
218/// assert_eq!(vec, vec![1, 2, 3, 4]);
219///
220/// // This is useful when you need to pass the data to a function that expects Vec<u8>
221/// fn process_bytes(data: Vec<u8>) -> usize {
222///     data.len()
223/// }
224///
225/// let bytes = ByteString::new([1, 2, 3, 4]);
226/// let size = process_bytes(bytes.into());
227/// assert_eq!(size, 4);
228/// ```
229impl From<ByteString> for Vec<u8> {
230    fn from(value: ByteString) -> Self {
231        value.0
232    }
233}
234
235/// Converts a `Vec<u8>` into a `ByteString`.
236///
237/// This conversion takes ownership of the vector, avoiding a copy operation.
238///
239/// # Examples
240///
241/// ```
242/// use dcbor::prelude::*;
243///
244/// let vec = vec![1, 2, 3, 4];
245/// let bytes = ByteString::from(vec);
246/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
247///
248/// // You can also use the .into() method
249/// let vec = vec![5, 6, 7, 8];
250/// let bytes: ByteString = vec.into();
251/// assert_eq!(bytes.data(), &[5, 6, 7, 8]);
252/// ```
253impl From<Vec<u8>> for ByteString {
254    fn from(value: Vec<u8>) -> Self {
255        Self(value)
256    }
257}
258
259/// Converts a reference to a `Vec<u8>` into a `ByteString`.
260///
261/// This conversion clones the vector data since it only has a reference.
262///
263/// # Examples
264///
265/// ```
266/// use dcbor::prelude::*;
267///
268/// let vec = vec![1, 2, 3, 4];
269/// let bytes = ByteString::from(&vec);
270/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
271///
272/// // The original vector is unchanged
273/// assert_eq!(vec, vec![1, 2, 3, 4]);
274/// ```
275impl From<&Vec<u8>> for ByteString {
276    fn from(value: &Vec<u8>) -> Self {
277        Self(value.clone())
278    }
279}
280
281/// Converts a byte slice into a `ByteString`.
282///
283/// This conversion clones the slice data since it only has a reference.
284///
285/// # Examples
286///
287/// ```
288/// use dcbor::prelude::*;
289///
290/// let slice: &[u8] = &[1, 2, 3, 4];
291/// let bytes = ByteString::from(slice);
292/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
293///
294/// // You can also use the From trait with array slices
295/// let array = [5, 6, 7, 8];
296/// let bytes = ByteString::from(&array[..]);
297/// assert_eq!(bytes.data(), &[5, 6, 7, 8]);
298/// ```
299impl From<&[u8]> for ByteString {
300    fn from(value: &[u8]) -> Self {
301        Self(value.to_vec())
302    }
303}
304
305/// Converts a string slice into a `ByteString`.
306///
307/// This conversion treats the string as UTF-8 and stores its raw byte representation.
308/// Note that this doesn't perform any additional encoding or normalization - it simply
309/// uses the raw UTF-8 bytes of the string.
310///
311/// # Examples
312///
313/// ```
314/// use dcbor::prelude::*;
315///
316/// let s = "hello";
317/// let bytes = ByteString::from(s);
318/// assert_eq!(bytes.data(), b"hello");
319///
320/// // UTF-8 multi-byte characters work as expected
321/// let s = "こんにちは"; // "hello" in Japanese
322/// let bytes = ByteString::from(s);
323/// assert_eq!(bytes.data(), "こんにちは".as_bytes());
324/// ```
325impl From<&str> for ByteString {
326    fn from(value: &str) -> Self {
327        Self(value.as_bytes().to_vec())
328    }
329}
330
331/// Converts a `ByteString` into a CBOR byte string value.
332///
333/// This conversion creates a CBOR item of major type 2 (byte string)
334/// containing the byte string's data.
335///
336/// # Examples
337///
338/// ```
339/// use dcbor::prelude::*;
340///
341/// let bytes = ByteString::new([1, 2, 3, 4]);
342/// let cbor = CBOR::from(bytes);
343///
344/// // The result is a CBOR byte string
345/// assert_eq!(cbor.diagnostic(), "h'01020304'");
346///
347/// // The encoding follows dCBOR rules
348/// assert_eq!(cbor.to_cbor_data(), vec![0x44, 0x01, 0x02, 0x03, 0x04]);
349/// //           0x44: byte string (major type 2) of length 4
350/// ```
351impl From<ByteString> for CBOR {
352    fn from(value: ByteString) -> Self {
353        CBOR::to_byte_string(value)
354    }
355}
356
357/// Attempts to convert a CBOR value into a `ByteString`.
358///
359/// This conversion succeeds if the CBOR value is a byte string (major type 2),
360/// otherwise it returns a `WrongType` error.
361///
362/// # Examples
363///
364/// ```
365/// use dcbor::prelude::*;
366///
367/// // Converting from a CBOR byte string works
368/// let cbor = CBOR::to_byte_string([1, 2, 3, 4]);
369/// let bytes: ByteString = cbor.try_into().unwrap();
370/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
371///
372/// // Converting from a different CBOR type fails
373/// let cbor = CBOR::from(42);
374/// let result: dcbor::Result<ByteString> = cbor.try_into();
375/// assert!(result.is_err());
376/// ```
377impl TryFrom<CBOR> for ByteString {
378    type Error = Error;
379
380    fn try_from(cbor: CBOR) -> Result<Self, Self::Error> {
381        Ok(CBOR::try_into_byte_string(cbor)?.into())
382    }
383}
384
385/// Converts a fixed-size byte array into a `ByteString`.
386///
387/// This provides a convenient way to create byte strings from array literals.
388///
389/// # Examples
390///
391/// ```
392/// use dcbor::prelude::*;
393///
394/// let bytes = ByteString::from([1, 2, 3, 4]);
395/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
396///
397/// // Works with arrays of any size
398/// let bytes = ByteString::from([0; 10]);
399/// assert_eq!(bytes.data(), &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
400/// ```
401impl<const N: usize> From<[u8; N]> for ByteString {
402    fn from(value: [u8; N]) -> Self {
403        Self(value.to_vec())
404    }
405}
406
407/// Converts a reference to a fixed-size byte array into a `ByteString`.
408///
409/// This avoids moving ownership of the array while still creating a byte string from it.
410///
411/// # Examples
412///
413/// ```
414/// use dcbor::prelude::*;
415///
416/// let array = [1, 2, 3, 4];
417/// let bytes = ByteString::from(&array);
418/// assert_eq!(bytes.data(), &[1, 2, 3, 4]);
419///
420/// // The original array is unchanged
421/// assert_eq!(array, [1, 2, 3, 4]);
422/// ```
423impl<const N: usize> From<&[u8; N]> for ByteString {
424    fn from(value: &[u8; N]) -> Self {
425        Self(value.to_vec())
426    }
427}
428
429/// Attempts to convert a `ByteString` into a fixed-size byte array.
430///
431/// This conversion succeeds only if the byte string has exactly the right length
432/// for the target array. If it has a different length, it returns a `TryFromSliceError`.
433///
434/// # Examples
435///
436/// ```
437/// use dcbor::prelude::*;
438///
439/// // When the lengths match, conversion succeeds
440/// let bytes = ByteString::new([1, 2, 3, 4]);
441/// let array: [u8; 4] = bytes.try_into().unwrap();
442/// assert_eq!(array, [1, 2, 3, 4]);
443/// // When the lengths don't match, conversion fails
444/// let bytes = ByteString::new([1, 2, 3]);
445/// let result: core::result::Result<[u8; 4], _> = bytes.try_into();
446/// assert!(result.is_err());
447/// ```
448impl<const N: usize> TryFrom<ByteString> for [u8; N] {
449    type Error = TryFromSliceError;
450
451    fn try_from(value: ByteString) -> Result<Self, Self::Error> {
452        value.0.as_slice().try_into()
453    }
454}
455
456/// Implements the `IntoIterator` trait for references to `ByteString`.
457///
458/// This allows using a byte string directly in a `for` loop, which will
459/// iterate over references to each byte.
460///
461/// # Examples
462///
463/// ```
464/// use dcbor::prelude::*;
465///
466/// let bytes = ByteString::new([1, 2, 3, 4]);
467///
468/// // You can use a for loop directly on a ByteString reference
469/// let mut sum = 0;
470/// for byte in &bytes {
471///     sum += *byte;
472/// }
473/// assert_eq!(sum, 10);
474///
475/// // This is equivalent to using the iter() method
476/// let mut product = 1;
477/// for byte in bytes.iter() {
478///     product *= *byte;
479/// }
480/// assert_eq!(product, 24);
481/// ```
482impl<'a> IntoIterator for &'a ByteString {
483    type Item = &'a u8;
484    type IntoIter = ByteStringIterator<'a>;
485
486    fn into_iter(self) -> Self::IntoIter {
487        self.iter()
488    }
489}
490
491/// Implements the `AsRef<[u8]>` trait for `ByteString`.
492///
493/// This allows a byte string to be used with functions that accept
494/// references to byte slices.
495///
496/// # Examples
497///
498/// ```
499/// use dcbor::prelude::*;
500///
501/// let bytes = ByteString::new([1, 2, 3, 4]);
502///
503/// // Function that takes anything that can be referenced as a byte slice
504/// fn first_byte(data: impl AsRef<[u8]>) -> Option<u8> {
505///     let slice = data.as_ref();
506///     slice.first().copied()
507/// }
508///
509/// assert_eq!(first_byte(&bytes), Some(1));
510/// ```
511impl AsRef<[u8]> for ByteString {
512    fn as_ref(&self) -> &[u8] {
513        &self.0
514    }
515}
516
517/// Implements the `Deref` trait for `ByteString`, allowing it to be treated as a slice.
518///
519/// This implementation makes it possible to use slice methods directly on a `ByteString`
520/// without explicitly calling `.data()` or `.as_ref()`.
521///
522/// # Examples
523///
524/// ```
525/// use dcbor::prelude::*;
526///
527/// let bytes = ByteString::new([1, 2, 3, 4]);
528///
529/// // You can use slice indexing directly
530/// assert_eq!(bytes[0], 1);
531/// assert_eq!(bytes[1..3], [2, 3]);
532///
533/// // You can use slice methods directly
534/// assert_eq!(bytes.first(), Some(&1));
535/// assert_eq!(bytes.last(), Some(&4));
536/// ```
537impl Deref for ByteString {
538    type Target = [u8];
539
540    fn deref(&self) -> &Self::Target {
541        &self.0
542    }
543}
544
545/// An iterator over the bytes in a `ByteString`.
546///
547/// This iterator yields references to each byte in the byte string in sequence.
548/// It is created by the `ByteString::iter()` method or by using the
549/// `IntoIterator` trait on a reference to a `ByteString`.
550///
551/// # Examples
552///
553/// ```
554/// use dcbor::prelude::*;
555///
556/// let bytes = ByteString::new([1, 2, 3]);
557/// let mut iter = bytes.iter();
558///
559/// assert_eq!(iter.next(), Some(&1));
560/// assert_eq!(iter.next(), Some(&2));
561/// assert_eq!(iter.next(), Some(&3));
562/// assert_eq!(iter.next(), None);
563/// ```
564pub struct ByteStringIterator<'a> {
565    /// The slice being iterated over
566    slice: &'a [u8],
567
568    /// The current position in the slice
569    pos: usize,
570}
571
572/// Implements the `Iterator` trait for `ByteStringIterator`.
573///
574/// This provides the core functionality for iterating over a byte string's contents.
575impl<'a> Iterator for ByteStringIterator<'a> {
576    type Item = &'a u8;
577
578    fn next(&mut self) -> Option<Self::Item> {
579        if self.pos < self.slice.len() {
580            let item = &self.slice[self.pos];
581            self.pos += 1;
582            Some(item)
583        } else {
584            None
585        }
586    }
587}
588
589#[cfg(test)]
590mod tests {
591    #[test]
592    fn test_1() {
593        use crate::prelude::*;
594        // When the lengths match, conversion succeeds
595        let bytes = ByteString::new([1, 2, 3, 4]);
596        let array: [u8; 4] = bytes.try_into().unwrap();
597        assert_eq!(array, [1, 2, 3, 4]);
598        // When the lengths don't match, conversion fails
599        let bytes = ByteString::new([1, 2, 3]);
600        let result: core::result::Result<[u8; 4], _> = bytes.try_into();
601        assert!(result.is_err());
602    }
603}