use pel::expression::Symbol;
use pel::runtime::value::Value as PelValue;
use pel::runtime::{Binding as PelBinding, Context, ValueHandler};
use pel::Reference;
use std::borrow::Borrow;
use std::collections::HashMap;
use std::fmt::Display;
use std::hash::Hash;
#[derive(Clone, Default, Debug)]
pub struct MapContext<K>
where
K: Eq + Hash + Display + Borrow<str>,
{
map: HashMap<K, PelValue>,
}
impl<K> MapContext<K>
where
K: Eq + Hash + Display + Borrow<str>,
{
pub fn new(map: HashMap<K, PelValue>) -> Self {
Self { map }
}
}
impl<K> Context for MapContext<K>
where
K: Eq + Hash + Display + Borrow<str>,
{
fn resolve(&self, symbol: &Symbol) -> PelBinding {
match self.map.get(symbol.as_str()) {
Some(val) => PelBinding::Available(val.clone()),
None => PelBinding::Unknown,
}
}
fn value_handler(&self, _reference: Reference) -> Option<&dyn ValueHandler> {
None
}
}
impl<K> ValueHandler for MapContext<K>
where
K: Eq + Hash + Display + Borrow<str>,
{
fn detach(&self) -> Option<PelValue> {
Some(PelValue::object(
self.map
.iter()
.map(|(k, v)| (k.to_string(), v.clone()))
.collect(),
))
}
fn select_by_key(&self, key: &str) -> Option<PelValue> {
Some(self.map.get(key).cloned().unwrap_or_else(PelValue::null))
}
}