Crate minijinja_stack_ref
source ·Expand description
An extension package to MiniJinja that allows stack borrows.
This is an experimental package. There might be soundness issues and there might be problems with the API. Please give feedback.
§Intro
When implementing dynamic objects for MiniJinja lifetimes a common hurdle can be lifetimes. That’s because MiniJinja requires that all values passed to the template are owned by the runtime engine. Thus it becomes impossible to carry non static lifetimes into the template.
This crate provides a solution to this issue by moving lifetime checks to the
runtime for MiniJinja objects. One first needs to create a Scope
with
the scope
function. It invokes a callback to which a scope is passed
which in turn then provides functionality to create Value
s to those
borrowed values such as the object_ref
method.
§Example
This example demonstrates how to pass borrowed information into a template:
use minijinja::value::{StructObject, Value};
use minijinja::{context, Environment};
use minijinja_stack_ref::scope;
struct State {
version: &'static str,
}
impl StructObject for State {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"version" => Some(Value::from(self.version)),
_ => None,
}
}
}
let mut env = Environment::new();
env.add_template(
"info",
"app version: {{ state.version }}\nitems: {{ items }}"
)
.unwrap();
let state = State {
version: env!("CARGO_PKG_VERSION"),
};
let items = [1u32, 2, 3, 4];
let rv = scope(|scope| {
let tmpl = env.get_template("info").unwrap();
tmpl.render(context! {
state => scope.struct_object_ref(&state),
items => scope.seq_object_ref(&items[..]),
}).unwrap()
});
println!("{}", rv);
§Reborrowing
If an object holds other complex values it can be interesting to again
return a reference to a member rather. In that case it becomes necessary
again to get access to the Scope
. This can be accomplished with the
reborrow
functionality which. It lets you return references to &self
from within an referenced object:
use minijinja::value::{StructObject, Value};
use minijinja::{context, Environment};
use minijinja_stack_ref::{reborrow, scope};
struct Config {
version: &'static str,
}
struct State {
config: Config,
}
impl StructObject for Config {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"version" => Some(Value::from(self.version)),
_ => None,
}
}
}
impl StructObject for State {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
// return a reference to the inner config through reborrowing
"config" => Some(reborrow(self, |slf, scope| {
scope.struct_object_ref(&slf.config)
})),
_ => None,
}
}
}
let mut env = Environment::new();
env.add_template(
"info",
"app version: {{ state.config.version }}"
)
.unwrap();
let state = State {
config: Config {
version: env!("CARGO_PKG_VERSION"),
}
};
let rv = scope(|scope| {
let tmpl = env.get_template("info").unwrap();
tmpl.render(context! {
state => scope.struct_object_ref(&state),
}).unwrap()
});
println!("{}", rv);
Structs§
- Captures the calling scope.
- A handle to an enclosed value.
Functions§
- Returns
true
if reborrowing is possible. - Reborrows a reference to a dynamic object with the scope’s lifetime.
- Invokes a function with a reference to the stack scope so values can be borrowed.