use crate::{
parsing,
resolver::{Locked, LockedResolver, ResolverState, Unlocked, UnlockedResolver},
};
use super::Resolver;
pub struct IndexedResolver<S: ResolverState, T>
{
vars: Vec<Vec<T>>,
_state: S,
}
impl<T> LockedResolver<T> for IndexedResolver<Locked, T> {}
impl<T> UnlockedResolver<T, IndexedResolver<Locked, T>> for IndexedResolver<Unlocked, T>
{
fn lock(self) -> IndexedResolver<Locked, T>
{
IndexedResolver {
vars: self.vars,
_state: Locked,
}
}
}
const ALPHABET_SIZE: usize = (b'z' - b'a' + 1) as usize;
const ALPHABET_START_USIZE: usize = b'a' as usize;
impl<S, T> Resolver<S, T> for IndexedResolver<S, T>
where
S: ResolverState,
{
#[inline(always)]
fn resolve(&self, name: &str) -> Option<&T>
{
let name_bytes = name.as_bytes();
let letter = name_bytes[0] as usize - ALPHABET_START_USIZE;
let idx = parsing::parse_usize(&name_bytes[1..]);
Some(&self.vars[letter][idx])
}
}
impl<S, T> IndexedResolver<S, T>
where
S: ResolverState,
{
pub fn set(&mut self, id: char, index: usize, value: T)
{
self.vars[id as usize - ALPHABET_START_USIZE][index] = value;
}
pub(crate) fn get(&self, id: usize, index: usize) -> Option<&T>
{
self.vars[id].get(index)
}
}
impl<T: Default + Clone> IndexedResolver<Unlocked, T>
{
pub fn new() -> Self
{
Self {
vars: vec![vec![]; ALPHABET_SIZE],
_state: Unlocked,
}
}
pub fn add_id(&mut self, id: char, len: usize)
{
self.vars[id as usize - ALPHABET_START_USIZE] = vec![T::default(); len]
}
}