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}