#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct TemplateOp(u16);
impl TemplateOp {
const ENTER_MAX_CODE: u16 = 0x7fff;
const ATTR_CODE: u16 = 0x8000;
const ATTR_CUSTOM_NS_CODE: u16 = 0x8001;
const TEXT_CODE: u16 = 0x8002;
const STATIC_BASE: u16 = 0x8003;
pub(crate) const MAX_CAP: usize = 16_383;
pub(crate) const fn enter(skip: u16, namespace: bool) -> Self {
if skip as usize > Self::MAX_CAP {
panic!("op skip exceeds packed op capacity");
}
Self((skip << 1) | namespace as u16)
}
pub(crate) const fn attr(namespace: bool) -> Self {
if namespace {
Self(Self::ATTR_CUSTOM_NS_CODE)
} else {
Self(Self::ATTR_CODE)
}
}
pub(crate) const fn text() -> Self {
Self(Self::TEXT_CODE)
}
pub(crate) const fn static_text(id: u16) -> Self {
if id as usize >= Self::MAX_CAP {
panic!("static op id exceeds packed op capacity");
}
Self(Self::STATIC_BASE + id)
}
pub(crate) const fn decode(self) -> DecodedTemplateOp {
if self.0 <= Self::ENTER_MAX_CODE {
DecodedTemplateOp::Enter {
skip: self.0 >> 1,
namespace: self.0 & 1 == 1,
}
} else if self.0 == Self::ATTR_CODE {
DecodedTemplateOp::Attr { namespace: false }
} else if self.0 == Self::ATTR_CUSTOM_NS_CODE {
DecodedTemplateOp::Attr { namespace: true }
} else if self.0 == Self::TEXT_CODE {
DecodedTemplateOp::Text
} else {
DecodedTemplateOp::Static(self.0 - Self::STATIC_BASE)
}
}
pub(crate) const fn bits(self) -> u16 {
self.0
}
}
impl std::fmt::Debug for TemplateOp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.decode().fmt(f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecodedTemplateOp {
Enter {
skip: u16,
namespace: bool,
},
Attr {
namespace: bool,
},
Text,
Static(u16),
}