#![allow(clippy::type_complexity)]
use std::{
collections::{HashMap, hash_map::RandomState},
hash::{Hash, BuildHasher},
ops::Deref,
marker::PhantomData,
};
use crate::{
Datum, Combiner,
parser::{OperatorBindings, DatumAllocator},
combiner::{OpFn, ApFn},
};
#[derive(Debug)]
pub struct HashMapOperatorBindings<DA, OR, AR, CE, S = RandomState>
where DA: DatumAllocator,
DA::TT: Hash + Eq,
DA::ET: Hash + Eq,
DA::DR: Hash + Eq,
S: BuildHasher,
{
pub hashmap: HashMap<Datum<DA::TT, DA::ET, DA::DR>, Combiner<OR, AR>, S>,
have_combiner_error_type: PhantomData<*const CE>,
}
impl<DA, OR, AR, CE, S>
HashMapOperatorBindings<DA, OR, AR, CE, S>
where DA: DatumAllocator,
DA::TT: Hash + Eq,
DA::ET: Hash + Eq,
DA::DR: Hash + Eq,
S: BuildHasher,
{
#[inline]
pub fn new(hashmap: HashMap<Datum<DA::TT, DA::ET, DA::DR>, Combiner<OR, AR>, S>)
-> Self
{
Self {
hashmap,
have_combiner_error_type: PhantomData,
}
}
}
impl<DA, OR, AR, CE, S>
Default
for HashMapOperatorBindings<DA, OR, AR, CE, S>
where DA: DatumAllocator,
DA::TT: Hash + Eq,
DA::ET: Hash + Eq,
DA::DR: Hash + Eq,
S: BuildHasher + Default,
{
#[inline]
fn default() -> Self {
Self::new(HashMap::default())
}
}
impl<DA, OR, AR, CE, S>
OperatorBindings<DA>
for HashMapOperatorBindings<DA, OR, AR, CE, S>
where DA: DatumAllocator,
DA::TT: Hash + Eq,
DA::ET: Hash + Eq,
DA::DR: Hash + Eq,
S: BuildHasher,
OR: Deref<Target = OpFn<DA, CE>>,
AR: Deref<Target = ApFn<DA, CE>>,
{
type OR = OR;
type AR = AR;
type CE = CE;
#[inline]
fn lookup(&self, operator: &Datum<DA::TT, DA::ET, DA::DR>)
-> Option<&Combiner<OR, AR>>
{
self.hashmap.get(operator)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
text::{Text, TextVec, chunk::PosStr},
parser::BoxDatumAllocator,
datum::DatumBox,
};
#[test]
#[allow(unused_results)]
fn basic() {
let mut hmob: HashMapOperatorBindings<BoxDatumAllocator<TextVec<PosStr<'_>>, ()>,
Box<OpFn<_, _>>, Box<ApFn<_, _>>, ()>
= HashMapOperatorBindings::default();
let rator = Datum::Text(TextVec::<PosStr<'_>>::from_str("rator"));
assert_eq!(hmob.lookup(&rator).map(|_| true), None);
hmob.hashmap.insert(rator.clone(),
Combiner::Operative(Box::new(|_, _, _| unreachable!())));
assert_eq!(hmob.lookup(&rator)
.map(|c| if let Combiner::Operative(_) = c { true }
else { false }),
Some(true));
assert_eq!(hmob.lookup(&Datum::EmptyNest).map(|_| true), None);
hmob.hashmap.remove(&rator);
assert_eq!(hmob.lookup(&rator).map(|_| true), None);
let compound = Datum::Combination{operator: DatumBox::new(Datum::Extra(())),
operands: DatumBox::new(Datum::EmptyList)};
assert_eq!(hmob.lookup(&compound).map(|_| true), None);
hmob.hashmap.insert(compound.clone(),
Combiner::Applicative(Box::new(|_, _, _| unreachable!())));
assert_eq!(hmob.lookup(&compound)
.map(|c| if let Combiner::Applicative(_) = c { true }
else { false }),
Some(true));
}
}