Skip to main content

rust_mqtt/
bytes.rs

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