Skip to main content

cbor_core/
bytes.rs

1use std::borrow::Cow;
2
3use crate::Value;
4
5/// Conversion helper for [`Value::byte_string`].
6///
7/// Wraps a `Cow<'a, [u8]>` so that [`Value::byte_string`] can accept
8/// owned and borrowed byte inputs through a single
9/// `impl Into<ByteString>` bound. This mirrors how
10/// [`Array`](crate::Array) and [`Map`](crate::Map) abstract their
11/// input shapes.
12///
13/// Supported source types:
14///
15/// - `&'a [u8]` (and any `&'a T` with `T: AsRef<[u8]>`) borrows zero-copy.
16/// - Owned `Vec<u8>` is moved without copying.
17/// - Fixed-size `[u8; N]` (by value) is copied into a `Vec<u8>`.
18/// - `Cow<'a, [u8]>` is preserved as-is.
19///
20/// ```
21/// # use cbor_core::Value;
22/// // Borrows from the slice:
23/// let buf: Vec<u8> = vec![1, 2, 3];
24/// let v = Value::byte_string(buf.as_slice());
25/// assert_eq!(v.as_bytes().unwrap(), &[1, 2, 3]);
26///
27/// // Owns its storage:
28/// let v = Value::byte_string(vec![1u8, 2, 3]);
29/// assert_eq!(v.as_bytes().unwrap(), &[1, 2, 3]);
30/// ```
31#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
32#[repr(transparent)]
33pub struct ByteString<'a>(Cow<'a, [u8]>);
34
35impl<'a> ByteString<'a> {
36    /// Create an empty byte string.
37    ///
38    /// The result is `Cow::Borrowed(&[])` and lives for any lifetime.
39    pub const fn new() -> Self {
40        Self(Cow::Borrowed(&[]))
41    }
42
43    /// Borrow the contents as a `&[u8]`.
44    pub fn as_bytes(&self) -> &[u8] {
45        self.0.as_ref()
46    }
47
48    /// Borrow the contents as a mutable `Vec<u8>`, cloning if the
49    /// inner `Cow` is currently borrowed.
50    pub fn as_bytes_mut(&mut self) -> &mut Vec<u8> {
51        self.0.to_mut()
52    }
53
54    /// Detach from any borrow, returning a `ByteString` with an
55    /// independent lifetime.
56    ///
57    /// A borrowed `ByteString<'a>` is copied into an owned `Vec<u8>`;
58    /// an already-owned one is returned unchanged. The result can
59    /// be assigned to any lifetime, in particular `ByteString<'static>`.
60    pub fn into_owned<'b>(self) -> ByteString<'b> {
61        match self.0 {
62            Cow::Borrowed(bytes) => ByteString(bytes.to_vec().into()),
63            Cow::Owned(bytes) => ByteString(bytes.into()),
64        }
65    }
66}
67
68impl<'a, T> From<&'a T> for ByteString<'a>
69where
70    T: AsRef<[u8]> + ?Sized,
71{
72    fn from(value: &'a T) -> Self {
73        Self(value.as_ref().into())
74    }
75}
76
77impl<'a> From<Vec<u8>> for ByteString<'a> {
78    fn from(value: Vec<u8>) -> Self {
79        Self(value.into())
80    }
81}
82
83impl<'a, const N: usize> From<[u8; N]> for ByteString<'a> {
84    fn from(value: [u8; N]) -> Self {
85        Self(value.to_vec().into())
86    }
87}
88
89impl<'a> From<Cow<'a, [u8]>> for ByteString<'a> {
90    fn from(value: Cow<'a, [u8]>) -> Self {
91        Self(value)
92    }
93}
94
95impl<'a> From<ByteString<'a>> for Value<'a> {
96    fn from(value: ByteString<'a>) -> Self {
97        Value::ByteString(value.0)
98    }
99}