rust_mqtt/
bytes.rs

1use core::{borrow::Borrow, fmt, ops::Deref};
2
3#[cfg(feature = "alloc")]
4use alloc::boxed::Box;
5
6/// Contiguous bytes in memory. Is either a `u8` slice or (with crate feature "alloc") an owned `Box<u8>`.
7///
8/// It is recommended to almost always use owned `Bytes<'a>` instead of a reference `&Bytes<'a>`,
9/// as it makes this type compatible for code designed for both owned and borrowed variants.
10///
11/// Important: Cloning this will clone the underlying Box if it is an owned variant.
12/// You can however borrow another owned `Bytes<'a>` by calling `as_borrowed()`.
13/// The `as_borrowed()` method is passed on through wrapper types, for example `MqttString`.
14pub enum Bytes<'a> {
15    /// Owned variant, only available with the `std` or `alloc` feature enabled.
16    #[cfg(feature = "alloc")]
17    Owned(Box<[u8]>),
18
19    /// Borrowed variant.
20    Borrowed(&'a [u8]),
21}
22
23impl<'a> Bytes<'a> {
24    /// Borrows `self` with its full lifetime to create another owned `Self` instance.
25    #[inline]
26    pub const fn as_borrowed(&'a self) -> Self {
27        match self {
28            #[cfg(feature = "alloc")]
29            Self::Owned(b) => Self::Borrowed(b),
30            Self::Borrowed(s) => Self::Borrowed(s),
31        }
32    }
33
34    /// Returns the number of bytes.
35    #[inline]
36    pub const fn len(&self) -> usize {
37        match self {
38            #[cfg(feature = "alloc")]
39            Self::Owned(b) => b.len(),
40            Self::Borrowed(s) => s.len(),
41        }
42    }
43
44    /// Returns whether the underlying data has a length of 0.
45    #[inline]
46    pub const fn is_empty(&self) -> bool {
47        self.len() == 0
48    }
49}
50
51impl<'a> Clone for Bytes<'a> {
52    fn clone(&self) -> Self {
53        match self {
54            #[cfg(feature = "alloc")]
55            Self::Owned(b) => Self::Owned(b.clone()),
56            Self::Borrowed(s) => Self::Borrowed(s),
57        }
58    }
59}
60
61#[cfg(feature = "alloc")]
62impl<'a> From<Bytes<'a>> for Box<[u8]> {
63    fn from(bytes: Bytes<'a>) -> Self {
64        match bytes {
65            Bytes::Owned(b) => b,
66            Bytes::Borrowed(s) => s.into(),
67        }
68    }
69}
70
71impl<'a> Default for Bytes<'a> {
72    fn default() -> Self {
73        Self::Borrowed(&[])
74    }
75}
76
77impl<'a> fmt::Debug for Bytes<'a> {
78    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79        match self {
80            Self::Borrowed(x) => f.debug_tuple("Borrowed").field(x).finish(),
81            #[cfg(feature = "alloc")]
82            Self::Owned(x) => f.debug_tuple("Owned").field(x).finish(),
83        }
84    }
85}
86
87#[cfg(feature = "defmt")]
88impl<'a> defmt::Format for Bytes<'a> {
89    fn format(&self, fmt: defmt::Formatter) {
90        match self {
91            Self::Borrowed(x) => defmt::write!(fmt, "Borrowed({:?})", *x),
92            #[cfg(feature = "alloc")]
93            Self::Owned(x) => defmt::write!(fmt, "Owned({:?})", x.as_ref()),
94        }
95    }
96}
97
98impl<'a> PartialEq for Bytes<'a> {
99    fn eq(&self, other: &Self) -> bool {
100        let one: &[u8] = self;
101        let other: &[u8] = other;
102
103        one == other
104    }
105}
106impl<'a> Eq for Bytes<'a> {}
107
108impl<'a> From<&'a mut [u8]> for Bytes<'a> {
109    fn from(value: &'a mut [u8]) -> Self {
110        Self::Borrowed(value)
111    }
112}
113impl<'a> From<&'a [u8]> for Bytes<'a> {
114    fn from(value: &'a [u8]) -> Self {
115        Self::Borrowed(value)
116    }
117}
118impl<'a> From<&'a mut str> for Bytes<'a> {
119    fn from(value: &'a mut str) -> Self {
120        Self::Borrowed(value.as_bytes())
121    }
122}
123impl<'a> From<&'a str> for Bytes<'a> {
124    fn from(value: &'a str) -> Self {
125        Self::Borrowed(value.as_bytes())
126    }
127}
128
129#[cfg(feature = "alloc")]
130impl<'a> From<Box<[u8]>> for Bytes<'a> {
131    fn from(value: Box<[u8]>) -> Self {
132        Self::Owned(value)
133    }
134}
135
136impl<'a> Deref for Bytes<'a> {
137    type Target = [u8];
138
139    fn deref(&self) -> &Self::Target {
140        match self {
141            Self::Borrowed(value) => value,
142            #[cfg(feature = "alloc")]
143            Self::Owned(value) => value,
144        }
145    }
146}
147
148impl<'a> Borrow<[u8]> for Bytes<'a> {
149    fn borrow(&self) -> &[u8] {
150        self
151    }
152}