use alloc::vec::Vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Runtime {
VueDom,
VueServerRenderer,
VueVapor,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Helper(u8);
impl Helper {
pub const LIMIT: usize = 128;
#[must_use]
pub const fn from_index(index: u8) -> Option<Self> {
if (index as usize) < Self::LIMIT {
Some(Self(index))
} else {
None
}
}
#[must_use]
pub const fn index(self) -> u8 {
self.0
}
const fn bit(self) -> u128 {
1u128 << self.0
}
}
#[derive(Debug)]
pub struct HelperModule {
pub module: &'static str,
pub names: &'static [&'static str],
}
#[derive(Debug)]
pub struct Vocabulary {
pub modules: &'static [HelperModule],
}
impl Vocabulary {
#[must_use]
pub fn name(&self, helper: Helper) -> Option<&'static str> {
self.export(helper).map(|(_, name)| name)
}
#[must_use]
pub fn export(&self, helper: Helper) -> Option<(&'static str, &'static str)> {
let mut index = usize::from(helper.index());
for module in self.modules {
if let Some(&name) = module.names.get(index) {
return Some((module.module, name));
}
index = index.checked_sub(module.names.len())?;
}
None
}
#[must_use]
pub fn helper(&self, name: &str) -> Option<Helper> {
let mut base = 0;
for module in self.modules {
if let Some(index) = module.names.iter().position(|candidate| *candidate == name) {
return u8::try_from(base + index).ok().and_then(Helper::from_index);
}
base += module.names.len();
}
None
}
}
mod vue;
pub use vue::{VUE_DOM, VUE_SERVER_RENDERER, VUE_VAPOR};
#[must_use]
pub fn vocabulary(runtime: Runtime) -> &'static Vocabulary {
match runtime {
Runtime::VueDom => &VUE_DOM,
Runtime::VueServerRenderer => &VUE_SERVER_RENDERER,
Runtime::VueVapor => &VUE_VAPOR,
}
}
#[must_use]
pub fn vocabulary_for(runtime: Runtime, version: &str) -> Option<&'static Vocabulary> {
match (runtime, version) {
(Runtime::VueDom | Runtime::VueServerRenderer, "3.5.35")
| (Runtime::VueVapor, "3.6.0-rc.9") => Some(vocabulary(runtime)),
_ => None,
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct HelperSet {
mask: u128,
order: Vec<Helper>,
}
impl HelperSet {
pub fn insert(&mut self, helper: Helper) -> bool {
if self.contains(helper) {
return false;
}
self.mask |= helper.bit();
self.order.push(helper);
true
}
#[must_use]
pub fn contains(&self, helper: Helper) -> bool {
self.mask & helper.bit() != 0
}
#[must_use]
pub fn in_use_order(&self) -> &[Helper] {
&self.order
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.order.is_empty()
}
pub fn extend(&mut self, other: &Self) {
for &helper in &other.order {
self.insert(helper);
}
}
}
#[cfg(test)]
mod tests;