use const_fn::const_fn;
use crate::{
bytes::Bytes,
fmt::const_debug_assert,
types::{MqttString, TooLargeToEncode},
};
#[derive(Default, Clone, PartialEq, Eq)]
pub struct MqttBinary<'b>(pub(crate) Bytes<'b>);
impl core::fmt::Debug for MqttBinary<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("MqttBinary").field(&self.as_ref()).finish()
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for MqttBinary<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "MqttBinary({:?})", self.as_ref());
}
}
impl<'b> TryFrom<&'b [u8]> for MqttBinary<'b> {
type Error = TooLargeToEncode;
fn try_from(value: &'b [u8]) -> Result<Self, Self::Error> {
Self::from_slice(value)
}
}
impl<'b> TryFrom<&'b str> for MqttBinary<'b> {
type Error = TooLargeToEncode;
fn try_from(value: &'b str) -> Result<Self, Self::Error> {
Self::from_slice(value.as_bytes())
}
}
impl<'b> From<MqttString<'b>> for MqttBinary<'b> {
fn from(value: MqttString<'b>) -> Self {
Self(value.0.0)
}
}
impl AsRef<[u8]> for MqttBinary<'_> {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl<'b> MqttBinary<'b> {
pub const MAX_LENGTH: usize = u16::MAX as usize;
#[const_fn(cfg(not(feature = "alloc")))]
pub const fn from_bytes(bytes: Bytes<'b>) -> Result<Self, TooLargeToEncode> {
match bytes.len() {
..=Self::MAX_LENGTH => Ok(Self(bytes)),
_ => Err(TooLargeToEncode),
}
}
pub const fn from_slice(slice: &'b [u8]) -> Result<Self, TooLargeToEncode> {
match slice.len() {
..=Self::MAX_LENGTH => Ok(Self(Bytes::Borrowed(slice))),
_ => Err(TooLargeToEncode),
}
}
#[must_use]
pub const fn from_bytes_unchecked(bytes: Bytes<'b>) -> Self {
const_debug_assert!(
bytes.len() <= Self::MAX_LENGTH,
"the slice's length exceeds MAX_LENGTH"
);
Self(bytes)
}
#[must_use]
pub const fn from_slice_unchecked(slice: &'b [u8]) -> Self {
const_debug_assert!(
slice.len() <= Self::MAX_LENGTH,
"the slice's length exceeds MAX_LENGTH"
);
Self(Bytes::Borrowed(slice))
}
#[inline]
#[must_use]
pub const fn len(&self) -> u16 {
self.0.len() as u16
}
#[inline]
#[must_use]
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
#[must_use]
pub const fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
#[inline]
#[must_use]
pub const fn as_borrowed(&'b self) -> Self {
Self(self.0.as_borrowed())
}
}