mod abs;
mod add;
mod all;
mod any;
mod append;
mod assert;
mod capitalize;
mod ceil;
mod cmp;
mod description;
mod diminish;
mod div;
mod empty;
mod eq;
mod escape;
mod filter;
mod filter_by_key;
mod find;
mod find_by_key;
mod first;
mod floor;
mod format_base64;
mod format_bool;
mod format_date;
mod format_input;
mod format_json;
mod format_lower;
mod format_paragraphs;
mod format_syntax;
mod format_tag;
mod format_upper;
mod get;
mod group;
mod gt;
mod gte;
mod has;
mod hide;
mod highlight;
mod insert;
mod internal_debug;
mod internal_json;
mod internal_tracer;
mod intersection;
mod is_bytes;
mod is_list;
mod is_map;
mod join;
mod key;
mod keys;
mod label;
mod last;
mod length;
mod lt;
mod lte;
mod map;
mod math;
mod meta;
mod mul;
mod ne;
mod not;
mod omit;
mod order;
mod pattern;
mod percent_decode;
mod percent_encode;
mod pick;
mod placeholder;
mod prepend;
mod quote;
mod reduce;
mod rem;
mod repeat;
mod replace;
mod rest;
mod round;
mod safe;
mod set;
mod slice;
mod sort;
mod span;
mod split;
mod strip_end;
mod strip_start;
mod sub;
mod toggle;
mod trace;
mod trim;
mod truncate;
mod truncate_start;
mod union;
mod values;
use crate::lang::adapter::Adapter;
use crate::lang::args::eval_args;
use crate::lang::arity::assert_func_arity;
use crate::lang::error::Error;
use crate::lang::error::ErrorKind;
use crate::lang::eval::eval_context_getter;
use crate::lang::label::Label;
use crate::lang::machine::Machine;
use crate::lang::node::Node;
use crate::value::Value;
use either::Either;
pub(crate) fn call(
adapter: &impl Adapter,
machine: &mut Machine<'_>,
stdin: Option<&Value>,
node: Node,
func: &[u8],
) -> Result<Either<Node, Value>, Error> {
let node = match call_adapter_func(adapter, machine, stdin, node, func)? {
Either::Right(value) => return Ok(Either::Right(value)),
Either::Left(node) => node,
};
if func.starts_with(b"internal") {
return call_internal_func(adapter, machine, stdin, node).map(Either::Right);
}
call_func(adapter, machine, stdin, node, func)
}
fn call_func(
adapter: &impl Adapter,
machine: &mut Machine<'_>,
span: Option<&Value>,
node: Node,
func: &[u8],
) -> Result<Either<Node, Value>, Error> {
Ok(Either::Right(match func {
b"abs" => abs::abs(adapter, machine, span, node)?,
b"add" => add::add(adapter, machine, span, node)?,
b"all" => all::all(adapter, machine, span, node)?,
b"any" => any::any(adapter, machine, span, node)?,
b"append" => append::append(adapter, machine, span, node)?,
b"assert" => assert::assert(adapter, machine, span, node)?,
b"capitalize" => capitalize::capitalize(adapter, machine, span, node)?,
b"ceil" => ceil::ceil(adapter, machine, span, node)?,
b"description" => description::description(adapter, machine, span, node)?,
b"diminish" => diminish::diminish(adapter, machine, span, node)?,
b"div" => div::div(adapter, machine, span, node)?,
b"empty" => empty::empty(adapter, machine, span, node)?,
b"eq" => eq::eq(adapter, machine, span, node)?,
b"escape" => escape::escape(adapter, machine, span, node)?,
b"filter" => filter::filter(adapter, machine, span, node)?,
b"filter-by-key" => filter_by_key::filter_by_key(adapter, machine, span, node)?,
b"find" => find::find(adapter, machine, span, node)?,
b"find-by-key" => find_by_key::find_by_key(adapter, machine, span, node)?,
b"first" => first::first(adapter, machine, span, node)?,
b"floor" => floor::floor(adapter, machine, span, node)?,
b"format-base64" => format_base64::format_base64(adapter, machine, span, node)?,
b"format-bool" => format_bool::format_bool(adapter, machine, span, node)?,
b"format-date" => format_date::format_date(adapter, machine, span, node)?,
b"format-input" => format_input::format_input(adapter, machine, span, node)?,
b"format-json" => format_json::format_json(adapter, machine, span, node)?,
b"format-lower" => format_lower::format_lower(adapter, machine, span, node)?,
b"format-paragraphs" => format_paragraphs::format_paragraphs(adapter, machine, span, node)?,
b"format-syntax" => format_syntax::format_syntax(adapter, machine, span, node)?,
b"format-tag" => format_tag::format_tag(adapter, machine, span, node)?,
b"format-upper" => format_upper::format_upper(adapter, machine, span, node)?,
b"get" => get::get(adapter, machine, span, node)?,
b"group" => group::group(adapter, machine, span, node)?,
b"gt" => gt::gt(adapter, machine, span, node)?,
b"gte" => gte::gte(adapter, machine, span, node)?,
b"has" => has::has(adapter, machine, span, node)?,
b"hide" => hide::hide(adapter, machine, span, node)?,
b"highlight" => highlight::highlight(adapter, machine, span, node)?,
b"insert" => insert::insert(adapter, machine, span, node)?,
b"intersection" => intersection::intersection(adapter, machine, span, node)?,
b"is-bytes" => is_bytes::is_bytes(adapter, machine, span, node)?,
b"is-list" => is_list::is_list(adapter, machine, span, node)?,
b"is-map" => is_map::is_map(adapter, machine, span, node)?,
b"join" => join::join(adapter, machine, span, node)?,
b"key" => key::key(adapter, machine, span, node)?,
b"keys" => keys::keys(adapter, machine, span, node)?,
b"label" => label::label(adapter, machine, span, node)?,
b"last" => last::last(adapter, machine, span, node)?,
b"length" => length::length(adapter, machine, span, node)?,
b"lt" => lt::lt(adapter, machine, span, node)?,
b"lte" => lte::lte(adapter, machine, span, node)?,
b"map" => map::map(adapter, machine, span, node)?,
b"meta" => meta::meta(adapter, machine, span, node)?,
b"mul" => mul::mul(adapter, machine, span, node)?,
b"ne" => ne::ne(adapter, machine, span, node)?,
b"not" => not::not(adapter, machine, span, node)?,
b"omit" => omit::omit(adapter, machine, span, node)?,
b"order" => order::order(adapter, machine, span, node)?,
b"pattern" => pattern::pattern(adapter, machine, span, node)?,
b"percent-decode" => percent_decode::percent_decode(adapter, machine, span, node)?,
b"percent-encode" => percent_encode::percent_encode(adapter, machine, span, node)?,
b"pick" => pick::pick(adapter, machine, span, node)?,
b"placeholder" => placeholder::placeholder(adapter, machine, span, node)?,
b"prepend" => prepend::prepend(adapter, machine, span, node)?,
b"quote" => quote::quote(adapter, machine, span, node)?,
b"reduce" => reduce::reduce(adapter, machine, span, node)?,
b"rem" => rem::rem(adapter, machine, span, node)?,
b"repeat" => repeat::repeat(adapter, machine, span, node)?,
b"replace" => replace::replace(adapter, machine, span, node)?,
b"rest" => rest::rest(adapter, machine, span, node)?,
b"round" => round::round(adapter, machine, span, node)?,
b"safe" => safe::safe(adapter, machine, span, node)?,
b"set" => set::set(adapter, machine, span, node)?,
b"slice" => slice::slice(adapter, machine, span, node)?,
b"sort" => sort::sort(adapter, machine, span, node)?,
b"span" => span::span(adapter, machine, span, node)?,
b"split" => split::split(adapter, machine, span, node)?,
b"strip-end" => strip_end::strip_end(adapter, machine, span, node)?,
b"strip-start" => strip_start::strip_start(adapter, machine, span, node)?,
b"sub" => sub::sub(adapter, machine, span, node)?,
b"toggle" => toggle::toggle(adapter, machine, span, node)?,
b"trace" => trace::trace(adapter, machine, span, node)?,
b"trim" => trim::trim(adapter, machine, span, node)?,
b"truncate" => truncate::truncate(adapter, machine, span, node)?,
b"truncate-start" => truncate_start::truncate_start(adapter, machine, span, node)?,
b"union" => union::union(adapter, machine, span, node)?,
b"values" => values::values(adapter, machine, span, node)?,
_ => return Ok(Either::Left(node)),
}))
}
fn call_internal_func(
adapter: &impl Adapter,
machine: &mut Machine<'_>,
stdin: Option<&Value>,
node: Node,
) -> Result<Value, Error> {
let name = node
.list()
.first()
.and_then(Node::as_label)
.map(Label::as_name);
match name {
Some(n) if n == b"internal-debug" => {
internal_debug::internal_debug(adapter, machine, stdin, node)
}
Some(n) if n == b"internal-tracer" => {
internal_tracer::internal_tracer(adapter, machine, stdin, node)
}
Some(n) if n == b"internal-json" => {
internal_json::internal_json(adapter, machine, stdin, node)
}
Some(n) if n.starts_with(b"internal") => {
Ok(eval_context_getter(adapter, machine, stdin, node)?.unwrap_or_default())
}
_ => Err(Error {
kind: ErrorKind::Func,
source: adapter.template_source().map(String::from),
span: machine.span,
message: "unknown internal func".into(),
}),
}
}
fn call_adapter_func(
adapter: &impl Adapter,
machine: &mut Machine<'_>,
stdin: Option<&Value>,
node: Node,
func: &[u8],
) -> Result<Either<Node, Value>, Error> {
let Some(arity) = adapter.func_find(func) else {
return Ok(Either::Left(node));
};
assert_func_arity(adapter, machine, stdin, &node, &arity)?;
let args = eval_args(adapter, machine, stdin, node)?;
adapter
.func_call(func, args)
.map(|v| Either::Right(v.unwrap_or_default()))
.map_err(|e| Error {
kind: ErrorKind::Func,
source: adapter.template_source().map(String::from),
span: machine.span,
message: e,
})
}