#[rustfmt::skip]
#[allow(clippy::upper_case_acronyms)]
mod generated;
pub(crate) use generated::Meaning;
use {
crate::{
phf_map::PhfMap,
xkb::{
interner::{Interned, Interner},
meaning::generated::LONGEST,
},
},
arrayvec::ArrayVec,
bstr::ByteSlice,
hashbrown::{HashMap, hash_map::Entry},
};
#[derive(Default)]
pub(crate) struct MeaningCache {
sensitive: HashMap<Interned, Meaning>,
insensitive: HashMap<Interned, Meaning>,
}
impl MeaningCache {
pub(crate) fn get_case_sensitive(&mut self, interner: &Interner, name: Interned) -> Meaning {
match self.sensitive.entry(name) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
let val = interner.get(name);
let meaning = generated::STRING_TO_MEANING[val.as_bytes()];
let res = match meaning.name().as_bytes() == val.as_bytes() {
true => meaning,
_ => Meaning::__Unknown,
};
e.insert(res);
res
}
}
}
pub(crate) fn get_case_insensitive(&mut self, interner: &Interner, name: Interned) -> Meaning {
match self.insensitive.entry(name) {
Entry::Occupied(e) => *e.get(),
Entry::Vacant(e) => {
let val = interner.get(name);
let res = if val.len() > LONGEST {
Meaning::__Unknown
} else {
let mut buffer = ArrayVec::<u8, LONGEST>::new();
for &c in val.as_bytes() {
buffer.push(c.to_ascii_lowercase());
}
let meaning = generated::LOWERCASE_TO_MEANING[buffer.as_bytes()];
match meaning.lowercase().as_bytes() == buffer.as_bytes() {
true => meaning,
_ => Meaning::__Unknown,
}
};
e.insert(res);
res
}
}
}
}