summaryrefslogtreecommitdiffstats
path: root/vendor/handlebars/src/helpers/scripting.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/handlebars/src/helpers/scripting.rs')
-rw-r--r--vendor/handlebars/src/helpers/scripting.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/vendor/handlebars/src/helpers/scripting.rs b/vendor/handlebars/src/helpers/scripting.rs
new file mode 100644
index 000000000..cec3b9763
--- /dev/null
+++ b/vendor/handlebars/src/helpers/scripting.rs
@@ -0,0 +1,111 @@
+use std::collections::{BTreeMap, HashMap};
+
+use crate::context::Context;
+use crate::error::RenderError;
+use crate::helpers::HelperDef;
+use crate::json::value::{PathAndJson, ScopedJson};
+use crate::registry::Registry;
+use crate::render::{Helper, RenderContext};
+
+use rhai::serde::{from_dynamic, to_dynamic};
+use rhai::{Dynamic, Engine, Scope, AST};
+
+use serde_json::value::Value as Json;
+
+pub(crate) struct ScriptHelper {
+ pub(crate) script: AST,
+}
+
+#[inline]
+fn call_script_helper<'reg: 'rc, 'rc>(
+ params: &[PathAndJson<'reg, 'rc>],
+ hash: &BTreeMap<&'reg str, PathAndJson<'reg, 'rc>>,
+ engine: &Engine,
+ script: &AST,
+) -> Result<ScopedJson<'reg, 'rc>, RenderError> {
+ let params: Dynamic = to_dynamic(params.iter().map(|p| p.value()).collect::<Vec<&Json>>())?;
+
+ let hash: Dynamic = to_dynamic(
+ hash.iter()
+ .map(|(k, v)| ((*k).to_owned(), v.value()))
+ .collect::<HashMap<String, &Json>>(),
+ )?;
+
+ let mut scope = Scope::new();
+ scope.push_dynamic("params", params);
+ scope.push_dynamic("hash", hash);
+
+ let result = engine
+ .eval_ast_with_scope::<Dynamic>(&mut scope, script)
+ .map_err(RenderError::from)?;
+
+ let result_json: Json = from_dynamic(&result)?;
+
+ Ok(ScopedJson::Derived(result_json))
+}
+
+impl HelperDef for ScriptHelper {
+ fn call_inner<'reg: 'rc, 'rc>(
+ &self,
+ h: &Helper<'reg, 'rc>,
+ reg: &'reg Registry<'reg>,
+ _ctx: &'rc Context,
+ _rc: &mut RenderContext<'reg, 'rc>,
+ ) -> Result<ScopedJson<'reg, 'rc>, RenderError> {
+ call_script_helper(h.params(), h.hash(), &reg.engine, &self.script)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::json::value::{PathAndJson, ScopedJson};
+ use rhai::Engine;
+
+ #[test]
+ fn test_dynamic_convert() {
+ let j0 = json! {
+ [{"name": "tomcat"}, {"name": "jetty"}]
+ };
+
+ let d0 = to_dynamic(&j0).unwrap();
+ assert_eq!("array", d0.type_name());
+
+ let j1 = json!({
+ "name": "tomcat",
+ "value": 4000,
+ });
+
+ let d1 = to_dynamic(&j1).unwrap();
+ assert_eq!("map", d1.type_name());
+ }
+
+ #[test]
+ fn test_to_json() {
+ let d0 = Dynamic::from("tomcat".to_owned());
+
+ assert_eq!(
+ Json::String("tomcat".to_owned()),
+ from_dynamic::<Json>(&d0).unwrap()
+ );
+ }
+
+ #[test]
+ fn test_script_helper_value_access() {
+ let engine = Engine::new();
+
+ let script = "let plen = len(params); let p0 = params[0]; let hlen = len(hash); let hme = hash[\"me\"]; plen + \",\" + p0 + \",\" + hlen + \",\" + hme";
+ let ast = engine.compile(&script).unwrap();
+
+ let params = vec![PathAndJson::new(None, ScopedJson::Derived(json!(true)))];
+ let hash = btreemap! {
+ "me" => PathAndJson::new(None, ScopedJson::Derived(json!("no"))),
+ "you" => PathAndJson::new(None, ScopedJson::Derived(json!("yes"))),
+ };
+
+ let result = call_script_helper(&params, &hash, &engine, &ast)
+ .unwrap()
+ .render();
+ assert_eq!("1,true,2,no", &result);
+ }
+}