use minijinja::Value;
use std::collections::HashMap;
pub struct Context {
inner: HashMap<String, Value>,
}
impl Context {
#[must_use]
pub fn new() -> Self {
Self {
inner: HashMap::new(),
}
}
pub fn from_iter<I, K, V>(iter: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
K: Into<String>,
V: Into<Value>,
{
let mut context = Self::new();
for (key, value) in iter {
context.insert(key, value);
}
context
}
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
self.inner.insert(key.into(), value.into());
}
pub fn update(&mut self, other: Context) {
self.inner.extend(other.inner);
}
#[must_use]
pub fn get(&self, key: &str) -> Option<&Value> {
self.inner.get(key)
}
pub fn remove(&mut self, key: &str) -> Option<Value> {
self.inner.remove(key)
}
#[must_use]
pub fn contains_key(&self, key: &str) -> bool {
self.inner.contains_key(key)
}
#[must_use]
pub fn len(&self) -> usize {
self.inner.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[must_use]
pub fn into_value(self) -> Value {
Value::from_serialize(self.inner)
}
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use minijinja::Environment;
use super::*;
#[test]
fn builds_minijinja_values() {
let mut context = Context::new();
context.insert("name", "Rjango");
context.insert("count", 3);
let mut env = Environment::new();
env.add_template("show.txt", "{{ name }} {{ count }}")
.expect("valid template");
let rendered = env
.get_template("show.txt")
.expect("template exists")
.render(context.into_value())
.expect("context renders");
assert_eq!(rendered, "Rjango 3");
}
#[test]
fn context_from_iter_builds_values() {
let context =
Context::from_iter([("name", Value::from("Rjango")), ("count", Value::from(2))]);
assert_eq!(context.get("name"), Some(&Value::from("Rjango")));
assert_eq!(context.get("count"), Some(&Value::from(2)));
assert!(context.contains_key("name"));
}
#[test]
fn context_update_merges() {
let mut primary = Context::from_iter([("name", Value::from("Rjango"))]);
let secondary =
Context::from_iter([("name", Value::from("Updated")), ("count", Value::from(3))]);
primary.update(secondary);
assert_eq!(primary.get("name"), Some(&Value::from("Updated")));
assert_eq!(primary.get("count"), Some(&Value::from(3)));
}
#[test]
fn context_get_and_remove() {
let mut context = Context::from_iter([("name", Value::from("Rjango"))]);
assert_eq!(context.get("name"), Some(&Value::from("Rjango")));
assert_eq!(context.remove("name"), Some(Value::from("Rjango")));
assert_eq!(context.get("name"), None);
assert!(!context.contains_key("name"));
}
#[test]
fn context_len_and_empty() {
let mut context = Context::new();
assert!(context.is_empty());
assert_eq!(context.len(), 0);
context.insert("name", "Rjango");
assert!(!context.is_empty());
assert_eq!(context.len(), 1);
}
}