macro_rules! ok {
($expr:expr) => {
match $expr {
Ok(val) => val,
Err(err) => return Err(err),
}
};
}
macro_rules! some {
($expr:expr) => {
match $expr {
Some(val) => val,
None => return None,
}
};
}
#[doc(hidden)]
pub mod __context {
use crate::value::Value;
use crate::Environment;
use std::collections::BTreeMap;
use std::rc::Rc;
#[inline(always)]
pub fn make() -> BTreeMap<&'static str, Value> {
BTreeMap::default()
}
#[inline(always)]
pub fn add(ctx: &mut BTreeMap<&'static str, Value>, key: &'static str, value: Value) {
ctx.insert(key, value);
}
#[inline(always)]
pub fn build(ctx: BTreeMap<&'static str, Value>) -> Value {
Value::from_object(ctx)
}
pub fn thread_local_env() -> Rc<Environment<'static>> {
thread_local! {
static ENV: Rc<Environment<'static>> = Rc::new(Environment::new());
}
ENV.with(|x| x.clone())
}
}
#[macro_export]
macro_rules! context {
() => {
$crate::__context::build($crate::__context::make())
};
(
$($key:ident $(=> $value:expr)?),*
$(, .. $ctx:expr),* $(,)?
) => {{
let mut ctx = $crate::__context::make();
$(
$crate::__context_pair!(ctx, $key $(=> $value)?);
)*
let ctx = $crate::__context::build(ctx);
let merge_ctx = [
$(
$crate::value::Value::from($ctx),
)*
];
if merge_ctx.is_empty() {
ctx
} else {
$crate::value::merge_maps(
merge_ctx.into_iter().rev().chain(::std::iter::once(ctx)))
}
}};
(
$(.. $ctx:expr),* $(,)?
) => {{
$crate::value::merge_maps([
$(
$crate::value::Value::from($ctx),
)*
].into_iter().rev())
}};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __context_pair {
($ctx:ident, $key:ident) => {{
$crate::__context_pair!($ctx, $key => $key);
}};
($ctx:ident, $key:ident => $value:literal) => {
$crate::__context::add(&mut $ctx, stringify!($key), $crate::value::Value::from($value));
};
($ctx:ident, $key:ident => context! { $($inner:tt)* }) => {
$crate::__context::add(&mut $ctx, stringify!($key), $crate::context! { $($inner)* });
};
($ctx:ident, $key:ident => context!($($inner:tt)*)) => {
$crate::__context::add(&mut $ctx, stringify!($key), $crate::context!($($inner)*));
};
($ctx:ident, $key:ident => $value:expr) => {
$crate::__context::add(
&mut $ctx,
stringify!($key),
$crate::value::Value::from_serialize(&$value),
);
};
}
#[macro_export]
macro_rules! args {
() => { &[][..] as &[$crate::value::Value] };
($($arg:tt)*) => { $crate::__args_helper!(branch [[$($arg)*]], [$($arg)*]) };
}
#[macro_export]
#[doc(hidden)]
macro_rules! __args_helper {
(branch [[]], $args:tt) => { $crate::__args_helper!(args $args) };
(branch [[$n:ident => $e:expr]], $args:tt) => { $crate::__args_helper!(kwargs $args) };
(branch [[$n:ident => $e:expr, $($r:tt)*]], $args:tt) => { $crate::__args_helper!(kwargs $args) };
(branch [[$e:expr]], $args:tt) => { $crate::__args_helper!(args $args) };
(branch [[$e:expr, $($rest:tt)*]], $args:tt) => { $crate::__args_helper!(branch [[$($rest)*]], $args) };
(args [$($arg:tt)*]) => {&{
let mut args = Vec::<$crate::value::Value>::new();
$crate::__args_helper!(peel args, args, false, [$($arg)*]);
args
}[..]};
(kwargs [$($arg:tt)*]) => {&{
let mut args = Vec::<$crate::value::Value>::new();
let mut kwargs = Vec::<(&str, $crate::value::Value)>::new();
$crate::__args_helper!(peel args, kwargs, false, [$($arg)*]);
args.push($crate::value::Kwargs::from_iter(kwargs.into_iter()).into());
args
}[..]};
(peel $args:ident, $kwargs:ident, $has_kwargs:ident, []) => {};
(peel $args:ident, $kwargs:ident, $has_kwargs:ident, [$name:ident => $expr:expr]) => {
$kwargs.push((stringify!($name), $crate::value::Value::from_serialize(&$expr)));
};
(peel $args:ident, $kwargs:ident, $has_kwargs:ident, [$name:ident => $expr:expr, $($rest:tt)*]) => {
$kwargs.push((stringify!($name), $crate::value::Value::from_serialize(&$expr)));
$crate::__args_helper!(peel $args, $kwargs, true, [$($rest)*]);
};
(peel $args:ident, $kwargs:ident, false, [$expr:expr]) => {
$args.push($crate::value::Value::from_serialize(&$expr));
};
(peel $args:ident, $kwargs:ident, false, [$expr:expr, $($rest:tt)*]) => {
$args.push($crate::value::Value::from_serialize(&$expr));
$crate::__args_helper!(peel $args, $kwargs, false, [$($rest)*]);
};
}
#[macro_export]
macro_rules! render {
(
in $env:expr,
$tmpl:expr
$(, $key:ident $(=> $value:expr)?)* $(,)?
) => {
($env).render_str($tmpl, $crate::context! { $($key $(=> $value)? ,)* })
.expect("failed to render expression")
};
(
$tmpl:expr
$(, $key:ident $(=> $value:expr)?)* $(,)?
) => {
$crate::render!(in $crate::__context::thread_local_env(), $tmpl, $($key $(=> $value)? ,)*)
}
}