#![allow(clippy::unusual_byte_groupings)]
use core::fmt;
use core::mem;
#[cfg(feature = "test")]
use crate::{Decode, Encode};
pub(crate) const DATA_MASK: u8 = 0b00_111111;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub(crate) enum Kind {
#[allow(unused)]
Reserved = 0b00_000000,
Prefix = 0b01_000000,
Sequence = 0b10_000000,
Continuation = 0b11_000000,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "test", derive(Encode, Decode))]
#[repr(transparent)]
#[cfg_attr(feature = "test", musli(crate, transparent))]
pub(crate) struct Tag {
repr: u8,
}
impl Tag {
#[inline]
pub(crate) const fn new(kind: Kind, data: u8) -> Self {
debug_assert!(data <= DATA_MASK, "Data must fit in DATA_MASK");
Self {
repr: kind as u8 | data,
}
}
#[inline]
pub(crate) const fn empty(kind: Kind) -> Self {
Self {
repr: kind as u8 | DATA_MASK,
}
}
#[inline]
pub(crate) const fn from_byte(repr: u8) -> Self {
Self { repr }
}
#[inline]
pub(crate) const fn byte(self) -> u8 {
self.repr
}
#[inline]
pub(crate) const fn kind(self) -> Kind {
unsafe { mem::transmute(self.repr & !DATA_MASK) }
}
#[inline]
pub(crate) const fn data_raw(self) -> u8 {
self.repr & DATA_MASK
}
#[inline]
pub(crate) const fn data(self) -> Option<u8> {
let data = self.data_raw();
if data == DATA_MASK { None } else { Some(data) }
}
#[inline]
pub(crate) const fn with_len(kind: Kind, len: usize) -> (Self, bool) {
if len < DATA_MASK as usize {
(Self::new(kind, len as u8), true)
} else {
(Self::new(kind, DATA_MASK), false)
}
}
}
impl fmt::Debug for Tag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Tag")
.field("kind", &self.kind())
.field("data", &self.data())
.finish()
}
}