1use std::collections::VecDeque;
2use std::io::Write;
3
4use crate::error::ExecError;
5use crate::node::*;
6use crate::template::Template;
7use crate::utils::is_true;
8
9use gtmpl_value::{Func, Value};
10
11const MAX_TEMPLATE_DEPTH: usize = 100_000;
12#[derive(Debug)]
13struct Variable {
14 name: String,
15 value: Value,
16}
17
18struct State<'a, 'b, T: Write> {
19 template: &'a Template,
20 writer: &'b mut T,
21 node: Option<&'a Nodes>,
22 vars: VecDeque<VecDeque<Variable>>,
23 depth: usize,
24}
25
26pub struct Context {
28 dot: Value,
29}
30
31impl Context {
32 pub fn empty() -> Context {
33 Context { dot: Value::Nil }
34 }
35
36 pub fn from<T>(value: T) -> Context
37 where
38 T: Into<Value>,
39 {
40 let serialized: Value = value.into();
41 Context { dot: serialized }
42 }
43}
44
45impl<'b> Template {
46 pub fn execute<T: Write>(&self, writer: &'b mut T, data: &Context) -> Result<(), ExecError> {
47 let mut vars: VecDeque<VecDeque<Variable>> = VecDeque::new();
48 let mut dot = VecDeque::new();
49 dot.push_back(Variable {
50 name: "$".to_owned(),
51 value: data.dot.clone(),
52 });
53 vars.push_back(dot);
54
55 let mut state = State {
56 template: self,
57 writer,
58 node: None,
59 vars,
60 depth: 0,
61 };
62
63 let root = self
64 .tree_set
65 .get(&self.name)
66 .and_then(|tree| tree.root.as_ref())
67 .ok_or_else(|| ExecError::IncompleteTemplate(self.name.clone()))?;
68 state.walk(data, root)?;
69
70 Ok(())
71 }
72
73 pub fn render(&self, data: &Context) -> Result<String, ExecError> {
74 let mut w: Vec<u8> = vec![];
75 self.execute(&mut w, data)?;
76 String::from_utf8(w).map_err(ExecError::Utf8ConversionFailed)
77 }
78}
79
80impl<'a, 'b, T: Write> State<'a, 'b, T> {
81 fn set_kth_last_var_value(&mut self, k: usize, value: Value) -> Result<(), ExecError> {
82 if let Some(last_vars) = self.vars.back_mut() {
83 let i = last_vars.len() - k;
84 if let Some(kth_last_var) = last_vars.get_mut(i) {
85 kth_last_var.value = value;
86 return Ok(());
87 }
88 return Err(ExecError::VarContextToSmall(k));
89 }
90 Err(ExecError::EmptyStack)
91 }
92
93 fn var_value(&self, key: &str) -> Result<Value, ExecError> {
94 for context in self.vars.iter().rev() {
95 for var in context.iter().rev() {
96 if var.name == key {
97 return Ok(var.value.clone());
98 }
99 }
100 }
101 Err(ExecError::VariableNotFound(key.to_string()))
102 }
103
104 fn walk_list(&mut self, ctx: &Context, node: &'a ListNode) -> Result<(), ExecError> {
105 for n in &node.nodes {
106 self.walk(ctx, n)?;
107 }
108 Ok(())
109 }
110
111 fn walk(&mut self, ctx: &Context, node: &'a Nodes) -> Result<(), ExecError> {
114 self.node = Some(node);
115 match *node {
116 Nodes::Action(ref n) => {
117 let val = self.eval_pipeline(ctx, &n.pipe)?;
118 if n.pipe.decl.is_empty() {
119 self.print_value(&val)?;
120 }
121 Ok(())
122 }
123 Nodes::If(_) | Nodes::With(_) => self.walk_if_or_with(node, ctx),
124 Nodes::Range(ref n) => self.walk_range(ctx, n),
125 Nodes::List(ref n) => self.walk_list(ctx, n),
126 Nodes::Text(ref n) => write!(self.writer, "{}", n).map_err(ExecError::IOError),
127 Nodes::Template(ref n) => self.walk_template(ctx, n),
128 _ => Err(ExecError::UnknownNode(node.clone())),
129 }
130 }
131
132 fn walk_template(&mut self, ctx: &Context, template: &TemplateNode) -> Result<(), ExecError> {
133 let name = match template.name {
134 PipeOrString::String(ref name) => name.to_owned(),
135 PipeOrString::Pipe(ref pipe) => {
136 if let Value::String(s) = self.eval_pipeline(ctx, pipe)? {
137 s
138 } else {
139 return Err(ExecError::PipelineMustYieldString);
140 }
141 }
142 };
143 if self.depth >= MAX_TEMPLATE_DEPTH {
144 return Err(ExecError::MaxTemplateDepth);
145 }
146 let tree = self.template.tree_set.get(&name);
147 if let Some(tree) = tree {
148 if let Some(ref root) = tree.root {
149 let mut vars = VecDeque::new();
150 let mut dot = VecDeque::new();
151 let value = if let Some(ref pipe) = template.pipe {
152 self.eval_pipeline(ctx, pipe)?
153 } else {
154 Value::NoValue
155 };
156 dot.push_back(Variable {
157 name: "$".to_owned(),
158 value: value.clone(),
159 });
160 vars.push_back(dot);
161 let mut new_state = State {
162 template: self.template,
163 writer: self.writer,
164 node: None,
165 vars,
166 depth: self.depth + 1,
167 };
168 return new_state.walk(&Context::from(value), root);
169 }
170 }
171 Err(ExecError::TemplateNotDefined(name))
172 }
173
174 fn eval_pipeline(&mut self, ctx: &Context, pipe: &PipeNode) -> Result<Value, ExecError> {
175 let mut val: Option<Value> = None;
176 for cmd in &pipe.cmds {
177 val = Some(self.eval_command(ctx, cmd, &val)?);
178 }
180 let val = val.ok_or_else(|| ExecError::ErrorEvaluatingPipe(pipe.clone()))?;
181 for var in &pipe.decl {
182 if pipe.is_assign == true {
183 let mut idx2 = -1;
184 let mut idx1 = -1;
185 for (k, v) in self.vars.iter().enumerate() {
186 for (k2, v2) in v.iter().enumerate() {
187 if v2.name == var.ident[0] {
188 idx2 = k2 as i32;
189 idx1 = k as i32;
190 }
191 }
192 }
193 self.vars[idx1 as usize].remove(idx2 as usize);
195 self.vars[idx1 as usize].insert(
196 idx2 as usize,
197 Variable {
198 name: var.ident[0].clone(),
199 value: val.clone(),
200 },
201 );
202 } else {
209 self.vars
212 .back_mut()
213 .map(|v| {
214 v.push_back(Variable {
215 name: var.ident[0].clone(),
216 value: val.clone(),
217 })
218 })
219 .ok_or(ExecError::EmptyStack)?;
220 }
221 }
222 Ok(val)
223 }
224
225 fn eval_command(
226 &mut self,
227 ctx: &Context,
228 cmd: &CommandNode,
229 val: &Option<Value>,
230 ) -> Result<Value, ExecError> {
231 let first_word = &cmd
232 .args
233 .first()
234 .ok_or_else(|| ExecError::NoArgsForCommandNode(cmd.clone()))?;
235
236 match *(*first_word) {
237 Nodes::Field(ref n) => return self.eval_field_node(ctx, n, &cmd.args, val),
238 Nodes::Variable(ref n) => return self.eval_variable_node(n, &cmd.args, val),
239 Nodes::Pipe(ref n) => return self.eval_pipeline(ctx, n),
240 Nodes::Chain(ref n) => return self.eval_chain_node(ctx, n, &cmd.args, val),
241 Nodes::Identifier(ref n) => return self.eval_function(ctx, n, &cmd.args, val),
242 _ => {}
243 }
244 not_a_function(&cmd.args, val)?;
245 match *(*first_word) {
246 Nodes::Bool(ref n) => Ok(n.value.clone()),
247 Nodes::Dot(_) => Ok(ctx.dot.clone()),
248 Nodes::Number(ref n) => Ok(n.value.clone()),
249 Nodes::String(ref n) => Ok(n.value.clone()),
250 _ => Err(ExecError::CannotEvaluateCommand((*first_word).clone())),
251 }
252 }
253
254 fn eval_function(
255 &mut self,
256 ctx: &Context,
257 ident: &IdentifierNode,
258 args: &[Nodes],
259 fin: &Option<Value>,
260 ) -> Result<Value, ExecError> {
261 let name = &ident.ident;
262 let function = self
263 .template
264 .funcs
265 .get(name.as_str())
266 .ok_or_else(|| ExecError::UndefinedFunction(name.to_string()))?;
267 self.eval_call(ctx, *function, args, fin)
268 }
269
270 fn eval_call(
271 &mut self,
272 ctx: &Context,
273 function: Func,
274 args: &[Nodes],
275 fin: &Option<Value>,
276 ) -> Result<Value, ExecError> {
277 let mut arg_vals = vec![];
278 if !args.is_empty() {
279 for arg in &args[1..] {
280 let val = self.eval_arg(ctx, arg)?;
281 arg_vals.push(val);
282 }
283 }
284 if let Some(ref f) = *fin {
285 arg_vals.push(f.clone());
286 }
287 function(&arg_vals).map_err(Into::into)
290 }
291
292 fn eval_chain_node(
293 &mut self,
294 ctx: &Context,
295 chain: &ChainNode,
296 args: &[Nodes],
297 fin: &Option<Value>,
298 ) -> Result<Value, ExecError> {
299 if chain.field.is_empty() {
300 return Err(ExecError::NoFieldsInEvalChainNode);
301 }
302 if let Nodes::Nil(_) = *chain.node {
303 return Err(ExecError::NullInChain(chain.clone()));
304 }
305 let pipe = self.eval_arg(ctx, &*chain.node)?;
306 self.eval_field_chain(&pipe, &chain.field, args, fin)
307 }
308
309 fn eval_arg(&mut self, ctx: &Context, node: &Nodes) -> Result<Value, ExecError> {
310 match *node {
311 Nodes::Dot(_) => Ok(ctx.dot.clone()),
312 Nodes::Field(ref n) => self.eval_field_node(ctx, n, &[], &None), Nodes::Variable(ref n) => self.eval_variable_node(n, &[], &None),
315 Nodes::Pipe(ref n) => self.eval_pipeline(ctx, n),
316 Nodes::Identifier(ref n) => self.eval_function(ctx, n, &[], &None),
318 Nodes::Chain(ref n) => self.eval_chain_node(ctx, n, &[], &None),
319 Nodes::String(ref n) => Ok(n.value.clone()),
320 Nodes::Bool(ref n) => Ok(n.value.clone()),
321 Nodes::Number(ref n) => Ok(n.value.clone()),
322 _ => Err(ExecError::InvalidArgument(node.clone())),
323 }
324 }
325
326 fn eval_field_node(
327 &mut self,
328 ctx: &Context,
329 field: &FieldNode,
330 args: &[Nodes],
331 fin: &Option<Value>,
332 ) -> Result<Value, ExecError> {
333 self.eval_field_chain(&ctx.dot, &field.ident, args, fin)
334 }
335
336 fn eval_field_chain(
337 &mut self,
338 receiver: &Value,
339 ident: &[String],
340 args: &[Nodes],
341 fin: &Option<Value>,
342 ) -> Result<Value, ExecError> {
343 let n = ident.len();
344 if n < 1 {
345 return Err(ExecError::FieldChainWithoutFields);
346 }
347 let mut r: Value = Value::from(0);
349 for (i, id) in ident.iter().enumerate().take(n - 1) {
350 r = self.eval_field(if i == 0 { receiver } else { &r }, id, &[], &None)?;
351 }
352 self.eval_field(if n == 1 { receiver } else { &r }, &ident[n - 1], args, fin)
353 }
354
355 fn eval_field(
356 &mut self,
357 receiver: &Value,
358 field_name: &str,
359 args: &[Nodes],
360 fin: &Option<Value>,
361 ) -> Result<Value, ExecError> {
362 let has_args = args.len() > 1 || fin.is_some();
363 if has_args {
364 return Err(ExecError::NotAFunctionButArguments(field_name.to_string()));
365 }
366 let ret = match *receiver {
367 Value::Object(ref o) => o
368 .get(field_name)
369 .cloned()
370 .ok_or_else(|| ExecError::NoFiledFor(field_name.to_string(), receiver.clone())),
371 Value::Map(ref o) => Ok(o.get(field_name).cloned().unwrap_or(Value::NoValue)),
372 _ => Err(ExecError::OnlyMapsAndObjectsHaveFields),
373 };
374 if let Ok(Value::Function(ref f)) = ret {
375 return (f.f)(&[receiver.clone()]).map_err(Into::into);
376 }
377 ret
378 }
379
380 fn eval_variable_node(
381 &mut self,
382 variable: &VariableNode,
383 args: &[Nodes],
384 fin: &Option<Value>,
385 ) -> Result<Value, ExecError> {
386 let val = self.var_value(&variable.ident[0])?;
387 if variable.ident.len() == 1 {
388 not_a_function(args, fin)?;
389 return Ok(val);
390 }
391 self.eval_field_chain(&val, &variable.ident[1..], args, fin)
392 }
393
394 fn walk_if_or_with(&mut self, node: &'a Nodes, ctx: &Context) -> Result<(), ExecError> {
396 let pipe = match *node {
397 Nodes::If(ref n) | Nodes::With(ref n) => &n.pipe,
398 _ => return Err(ExecError::ExpectedIfOrWith(node.clone())),
399 };
400 let val = self.eval_pipeline(ctx, pipe)?;
401 let truth = is_true(&val);
402 if truth {
403 match *node {
404 Nodes::If(ref n) => self.walk_list(ctx, &n.list)?,
405 Nodes::With(ref n) => {
406 let ctx = Context { dot: val };
407 self.walk_list(&ctx, &n.list)?;
408 }
409 _ => {}
410 }
411 } else {
412 match *node {
413 Nodes::If(ref n) | Nodes::With(ref n) => {
414 if let Some(ref otherwise) = n.else_list {
415 self.walk_list(ctx, otherwise)?;
416 }
417 }
418 _ => {}
419 }
420 }
421 Ok(())
422 }
423
424 fn one_iteration(
425 &mut self,
426 key: Value,
427 val: Value,
428 range: &'a RangeNode,
429 ) -> Result<(), ExecError> {
430 if !range.pipe.decl.is_empty() {
431 self.set_kth_last_var_value(1, val.clone())?;
432 }
433 if range.pipe.decl.len() > 1 {
434 self.set_kth_last_var_value(2, key)?;
435 }
436 let vars = VecDeque::new();
437 self.vars.push_back(vars);
438 let ctx = Context { dot: val };
439 self.walk_list(&ctx, &range.list)?;
440 self.vars.pop_back();
441 Ok(())
442 }
443
444 fn walk_range(&mut self, ctx: &Context, range: &'a RangeNode) -> Result<(), ExecError> {
445 let val = self.eval_pipeline(ctx, &range.pipe)?;
446 match val {
447 Value::Object(ref map) | Value::Map(ref map) => {
448 for (k, v) in map.clone() {
449 self.one_iteration(Value::from(k), v, range)?;
450 }
451 }
452 Value::Array(ref vec) => {
453 for (k, v) in vec.iter().enumerate() {
454 self.one_iteration(Value::from(k), v.clone(), range)?;
455 }
456 }
457 _ => return Err(ExecError::InvalidRange(val)),
458 }
459 if let Some(ref else_list) = range.else_list {
460 self.walk_list(ctx, else_list)?;
461 }
462 Ok(())
463 }
464
465 fn print_value(&mut self, val: &Value) -> Result<(), ExecError> {
466 write!(self.writer, "{}", val).map_err(ExecError::IOError)?;
467 Ok(())
468 }
469}
470
471fn not_a_function(args: &[Nodes], val: &Option<Value>) -> Result<(), ExecError> {
472 if args.len() > 1 || val.is_some() {
473 return Err(ExecError::ArgumentForNonFunction(args[0].clone()));
474 }
475 Ok(())
476}
477
478#[cfg(test)]
479mod tests_mocked {
480 use super::*;
481 use anyhow::anyhow;
482 use gtmpl_derive::Gtmpl;
483 use gtmpl_value::FuncError;
484 use std::collections::HashMap;
485
486 #[test]
487 fn simple_template() {
488 let data = Context::from(1);
489 let mut w: Vec<u8> = vec![];
490 let mut t = Template::default();
491 assert!(t.parse(r#"{{ if false }} 2000 {{ end }}"#).is_ok());
492 let out = t.execute(&mut w, &data);
493 assert!(out.is_ok());
494 assert_eq!(String::from_utf8(w).unwrap(), "");
495
496 let data = Context::from(1);
497 let mut w: Vec<u8> = vec![];
498 let mut t = Template::default();
499 assert!(t.parse(r#"{{ if true }} 2000 {{ end }}"#).is_ok());
500 let out = t.execute(&mut w, &data);
501 assert!(out.is_ok());
502 assert_eq!(String::from_utf8(w).unwrap(), " 2000 ");
503
504 let data = Context::from(1);
505 let mut w: Vec<u8> = vec![];
506 let mut t = Template::default();
507 assert!(t.parse(r#"{{ if true -}} 2000 {{- end }}"#).is_ok());
508 let out = t.execute(&mut w, &data);
509 assert!(out.is_ok());
510 assert_eq!(String::from_utf8(w).unwrap(), "2000");
511
512 let data = Context::from(1);
513 let mut w: Vec<u8> = vec![];
514 let mut t = Template::default();
515 assert!(t
516 .parse(r#"{{ if false -}} 2000 {{- else -}} 3000 {{- end }}"#)
517 .is_ok());
518 let out = t.execute(&mut w, &data);
519 assert!(out.is_ok());
520 assert_eq!(String::from_utf8(w).unwrap(), "3000");
521 }
522
523 #[test]
524 fn test_dot() {
525 let data = Context::from(1);
526 let mut w: Vec<u8> = vec![];
527 let mut t = Template::default();
528 assert!(t
529 .parse(r#"{{ if . -}} 2000 {{- else -}} 3000 {{- end }}"#)
530 .is_ok());
531 let out = t.execute(&mut w, &data);
532 assert!(out.is_ok());
533 assert_eq!(String::from_utf8(w).unwrap(), "2000");
534
535 let data = Context::from(false);
536 let mut w: Vec<u8> = vec![];
537 let mut t = Template::default();
538 assert!(t
539 .parse(r#"{{ if . -}} 2000 {{- else -}} 3000 {{- end }}"#)
540 .is_ok());
541 let out = t.execute(&mut w, &data);
542 assert!(out.is_ok());
543 assert_eq!(String::from_utf8(w).unwrap(), "3000");
544 }
545
546 #[test]
547 fn test_sub() {
548 let data = Context::from(1u8);
549 let mut w: Vec<u8> = vec![];
550 let mut t = Template::default();
551 assert!(t.parse(r#"{{.}}"#).is_ok());
552 let out = t.execute(&mut w, &data);
553 assert!(out.is_ok());
554 assert_eq!(String::from_utf8(w).unwrap(), "1");
555
556 #[derive(Gtmpl)]
557 struct Foo {
558 foo: u8,
559 }
560 let f = Foo { foo: 1 };
561 let data = Context::from(f);
562 let mut w: Vec<u8> = vec![];
563 let mut t = Template::default();
564 assert!(t.parse(r#"{{.foo}}"#).is_ok());
565 let out = t.execute(&mut w, &data);
566 assert!(out.is_ok());
567 assert_eq!(String::from_utf8(w).unwrap(), "1");
568 }
569
570 #[test]
571 fn test_novalue() {
572 #[derive(Gtmpl)]
573 struct Foo {
574 foo: u8,
575 }
576 let f = Foo { foo: 1 };
577 let data = Context::from(f);
578 let mut w: Vec<u8> = vec![];
579 let mut t = Template::default();
580 assert!(t.parse(r#"{{.foobar}}"#).is_ok());
581 let out = t.execute(&mut w, &data);
582 assert!(out.is_err());
583
584 let map: HashMap<String, u64> = [("foo".to_owned(), 23u64)].iter().cloned().collect();
585 let data = Context::from(map);
586 let mut w: Vec<u8> = vec![];
587 let mut t = Template::default();
588 assert!(t.parse(r#"{{.foo2}}"#).is_ok());
589 let out = t.execute(&mut w, &data);
590 assert!(out.is_ok());
591 assert_eq!(String::from_utf8(w).unwrap(), Value::NoValue.to_string());
592 }
593
594 #[test]
595 fn test_dollar_dot() {
596 #[derive(Gtmpl, Clone)]
597 struct Foo {
598 foo: u8,
599 }
600 let data = Context::from(Foo { foo: 1u8 });
601 let mut w: Vec<u8> = vec![];
602 let mut t = Template::default();
603 assert!(t.parse(r#"{{$.foo}}"#).is_ok());
604 let out = t.execute(&mut w, &data);
605 assert!(out.is_ok());
606 assert_eq!(String::from_utf8(w).unwrap(), "1");
607 }
608
609 #[test]
610 fn test_function_via_dot() {
611 #[derive(Gtmpl)]
612 struct Foo {
613 foo: Func,
614 }
615 fn foo(_: &[Value]) -> Result<Value, FuncError> {
616 Ok(Value::from("foobar"))
617 }
618 let data = Context::from(Foo { foo });
619 let mut w: Vec<u8> = vec![];
620 let mut t = Template::default();
621 assert!(t.parse(r#"{{.foo}}"#).is_ok());
622 let out = t.execute(&mut w, &data);
623 assert!(out.is_ok());
624 assert_eq!(String::from_utf8(w).unwrap(), "foobar");
625
626 fn plus_one(args: &[Value]) -> Result<Value, FuncError> {
627 if let Value::Object(ref o) = &args[0] {
628 if let Some(Value::Number(ref n)) = o.get("num") {
629 if let Some(i) = n.as_i64() {
630 return Ok((i + 1).into());
631 }
632 }
633 }
634 Err(anyhow!("integer required, got: {:?}", args).into())
635 }
636
637 #[derive(Gtmpl)]
638 struct AddMe {
639 num: u8,
640 plus_one: Func,
641 }
642 let data = Context::from(AddMe { num: 42, plus_one });
643 let mut w: Vec<u8> = vec![];
644 let mut t = Template::default();
645 assert!(t.parse(r#"{{.plus_one}}"#).is_ok());
646 let out = t.execute(&mut w, &data);
647 assert!(out.is_ok());
648 assert_eq!(String::from_utf8(w).unwrap(), "43");
649 }
650
651 #[test]
652 fn test_function_ret_map() {
653 fn map(_: &[Value]) -> Result<Value, FuncError> {
654 let mut h = HashMap::new();
655 h.insert("field".to_owned(), 1);
656 Ok(h.into())
657 }
658
659 let data = Context::empty();
660 let mut w: Vec<u8> = vec![];
661 let mut t = Template::default();
662 t.add_func("map", map);
663 assert!(t.parse(r#"{{map.field}}"#).is_ok());
664 let out = t.execute(&mut w, &data);
665 assert!(out.is_ok());
666 assert_eq!(String::from_utf8(w).unwrap(), "1");
667 }
668
669 #[test]
670 fn test_dot_value() {
671 #[derive(Gtmpl, Clone)]
672 struct Foo {
673 foo: u8,
674 }
675 #[derive(Gtmpl)]
676 struct Bar {
677 bar: Foo,
678 }
679 let f = Foo { foo: 1 };
680 let data = Context::from(f);
681 let mut w: Vec<u8> = vec![];
682 let mut t = Template::default();
683 assert!(t
684 .parse(r#"{{ if .foo -}} 2000 {{- else -}} 3000 {{- end }}"#)
685 .is_ok());
686 let out = t.execute(&mut w, &data);
687 assert!(out.is_ok());
688 assert_eq!(String::from_utf8(w).unwrap(), "2000");
689
690 let f = Foo { foo: 0 };
691 let data = Context::from(f);
692 let mut w: Vec<u8> = vec![];
693 let mut t = Template::default();
694 assert!(t
695 .parse(r#"{{ if .foo -}} 2000 {{- else -}} 3000 {{- end }}"#)
696 .is_ok());
697 let out = t.execute(&mut w, &data);
698 assert!(out.is_ok());
699 assert_eq!(String::from_utf8(w).unwrap(), "3000");
700
701 let bar = Bar {
702 bar: Foo { foo: 1 },
703 };
704 let data = Context::from(bar);
705 let mut w: Vec<u8> = vec![];
706 let mut t = Template::default();
707 assert!(t
708 .parse(r#"{{ if .bar.foo -}} 2000 {{- else -}} 3000 {{- end }}"#)
709 .is_ok());
710 let out = t.execute(&mut w, &data);
711 assert!(out.is_ok());
712 assert_eq!(String::from_utf8(w).unwrap(), "2000");
713
714 let bar = Bar {
715 bar: Foo { foo: 0 },
716 };
717 let data = Context::from(bar);
718 let mut w: Vec<u8> = vec![];
719 let mut t = Template::default();
720 assert!(t
721 .parse(r#"{{ if .bar.foo -}} 2000 {{- else -}} 3000 {{- end }}"#)
722 .is_ok());
723 let out = t.execute(&mut w, &data);
724 assert!(out.is_ok());
725 assert_eq!(String::from_utf8(w).unwrap(), "3000");
726 }
727
728 #[test]
729 fn test_with() {
730 #[derive(Gtmpl)]
731 struct Foo {
732 foo: u16,
733 }
734 let f = Foo { foo: 1000 };
735 let data = Context::from(f);
736 let mut w: Vec<u8> = vec![];
737 let mut t = Template::default();
738 assert!(t
739 .parse(r#"{{ with .foo -}} {{.}} {{- else -}} 3000 {{- end }}"#)
740 .is_ok());
741 let out = t.execute(&mut w, &data);
742 assert!(out.is_ok());
743 assert_eq!(String::from_utf8(w).unwrap(), "1000");
744 }
745
746 fn to_sorted_string(buf: Vec<u8>) -> String {
747 let mut chars: Vec<char> = String::from_utf8(buf).unwrap().chars().collect();
748 chars.sort_unstable();
749 chars.iter().cloned().collect::<String>()
750 }
751
752 #[test]
753 fn test_range() {
754 let mut map = HashMap::new();
755 map.insert("a".to_owned(), 1);
756 map.insert("b".to_owned(), 2);
757 let data = Context::from(map);
758 let mut w: Vec<u8> = vec![];
759 let mut t = Template::default();
760 assert!(t.parse(r#"{{ range . -}} {{.}} {{- end }}"#).is_ok());
761 let out = t.execute(&mut w, &data);
762 assert!(out.is_ok());
763 assert_eq!(to_sorted_string(w), "12");
764
765 let vec = vec!["foo", "bar", "2000"];
766 let data = Context::from(vec);
767 let mut w: Vec<u8> = vec![];
768 let mut t = Template::default();
769 assert!(t.parse(r#"{{ range . -}} {{.}} {{- end }}"#).is_ok());
770 let out = t.execute(&mut w, &data);
771 assert!(out.is_ok());
772 assert_eq!(String::from_utf8(w).unwrap(), "foobar2000");
773 }
774
775 #[test]
776 fn test_proper_range() {
777 let vec = vec!["a".to_string(), "b".to_string()];
778 let data = Context::from(vec);
779 let mut w: Vec<u8> = vec![];
780 let mut t = Template::default();
781 assert!(t
782 .parse(r#"{{ range $k, $v := . -}} {{ $k }}{{ $v }} {{- end }}"#)
783 .is_ok());
784 let out = t.execute(&mut w, &data);
785 assert!(out.is_ok());
786 assert_eq!(String::from_utf8(w).unwrap(), "0a1b");
787
788 let mut map = HashMap::new();
789 map.insert("a".to_owned(), 1);
790 map.insert("b".to_owned(), 2);
791 let data = Context::from(map);
792 let mut w: Vec<u8> = vec![];
793 let mut t = Template::default();
794 assert!(t
795 .parse(r#"{{ range $k, $v := . -}} {{ $v }} {{- end }}"#)
796 .is_ok());
797 let out = t.execute(&mut w, &data);
798 assert!(out.is_ok());
799 assert_eq!(to_sorted_string(w), "12");
800
801 let mut map = HashMap::new();
802 map.insert("a".to_owned(), "b");
803 map.insert("c".to_owned(), "d");
804 let data = Context::from(map);
805 let mut w: Vec<u8> = vec![];
806 let mut t = Template::default();
807 assert!(t
808 .parse(r#"{{ range $k, $v := . -}} {{ $k }}{{ $v }} {{- end }}"#)
809 .is_ok());
810 let out = t.execute(&mut w, &data);
811 assert!(out.is_ok());
812 assert_eq!(to_sorted_string(w), "abcd");
813
814 let mut map = HashMap::new();
815 map.insert("a".to_owned(), 1);
816 map.insert("b".to_owned(), 2);
817 let data = Context::from(map);
818 let mut w: Vec<u8> = vec![];
819 let mut t = Template::default();
820 assert!(t
821 .parse(r#"{{ range $k, $v := . -}} {{ $k }}{{ $v }} {{- end }}"#)
822 .is_ok());
823 let out = t.execute(&mut w, &data);
824 assert!(out.is_ok());
825 assert_eq!(to_sorted_string(w), "12ab");
826
827 let mut map = HashMap::new();
828 map.insert("a".to_owned(), 1);
829 map.insert("b".to_owned(), 2);
830 #[derive(Gtmpl)]
831 struct Foo {
832 foo: HashMap<String, i32>,
833 }
834 let f = Foo { foo: map };
835 let data = Context::from(f);
836 let mut w: Vec<u8> = vec![];
837 let mut t = Template::default();
838 assert!(t
839 .parse(r#"{{ range $k, $v := .foo -}} {{ $v }} {{- end }}"#)
840 .is_ok());
841 let out = t.execute(&mut w, &data);
842 assert!(out.is_ok());
843 assert_eq!(to_sorted_string(w), "12");
844
845 let mut map = HashMap::new();
846 #[derive(Gtmpl, Clone)]
847 struct Bar {
848 bar: i32,
849 }
850 map.insert("a".to_owned(), Bar { bar: 1 });
851 map.insert("b".to_owned(), Bar { bar: 2 });
852 let data = Context::from(map);
853 let mut w: Vec<u8> = vec![];
854 let mut t = Template::default();
855 assert!(t
856 .parse(r#"{{ range $k, $v := . -}} {{ $v.bar }} {{- end }}"#)
857 .is_ok());
858 let out = t.execute(&mut w, &data);
859 assert!(out.is_ok());
860 assert_eq!(to_sorted_string(w), "12");
861 }
862
863 #[test]
864 fn test_len() {
865 let mut w: Vec<u8> = vec![];
866 let mut t = Template::default();
867 assert!(t.parse(r#"my len is {{ len . }}"#).is_ok());
868 let data = Context::from(vec![1, 2, 3]);
869 let out = t.execute(&mut w, &data);
870 assert!(out.is_ok());
871 assert_eq!(String::from_utf8(w).unwrap(), "my len is 3");
872
873 let mut w: Vec<u8> = vec![];
874 let mut t = Template::default();
875 assert!(t.parse(r#"{{ len . }}"#).is_ok());
876 let data = Context::from("hello".to_owned());
877 let out = t.execute(&mut w, &data);
878 assert!(out.is_ok());
879 assert_eq!(String::from_utf8(w).unwrap(), "5");
880 }
881
882 #[test]
883 fn test_pipeline_function() {
884 let mut w: Vec<u8> = vec![];
885 let mut t = Template::default();
886 assert!(t.parse(r#"{{ if ( 1 | eq . ) -}} 2000 {{- end }}"#).is_ok());
887 let data = Context::from(1);
888 let out = t.execute(&mut w, &data);
889 assert!(out.is_ok());
890 assert_eq!(String::from_utf8(w).unwrap(), "2000");
891 }
892
893 #[test]
894 fn test_function() {
895 let mut w: Vec<u8> = vec![];
896 let mut t = Template::default();
897 assert!(t.parse(r#"{{ if eq . . -}} 2000 {{- end }}"#).is_ok());
898 let data = Context::from(1);
899 let out = t.execute(&mut w, &data);
900 assert!(out.is_ok());
901 assert_eq!(String::from_utf8(w).unwrap(), "2000");
902 }
903
904 #[test]
905 fn test_eq() {
906 let mut w: Vec<u8> = vec![];
907 let mut t = Template::default();
908 assert!(t.parse(r#"{{ if eq "a" "a" -}} 2000 {{- end }}"#).is_ok());
909 let data = Context::from(1);
910 let out = t.execute(&mut w, &data);
911 assert!(out.is_ok());
912 assert_eq!(String::from_utf8(w).unwrap(), "2000");
913
914 let mut w: Vec<u8> = vec![];
915 let mut t = Template::default();
916 assert!(t.parse(r#"{{ if eq "a" "b" -}} 2000 {{- end }}"#).is_ok());
917 let data = Context::from(1);
918 let out = t.execute(&mut w, &data);
919 assert!(out.is_ok());
920 assert_eq!(String::from_utf8(w).unwrap(), "");
921
922 let mut w: Vec<u8> = vec![];
923 let mut t = Template::default();
924 assert!(t.parse(r#"{{ if eq true true -}} 2000 {{- end }}"#).is_ok());
925 let data = Context::from(1);
926 let out = t.execute(&mut w, &data);
927 assert!(out.is_ok());
928 assert_eq!(String::from_utf8(w).unwrap(), "2000");
929
930 let mut w: Vec<u8> = vec![];
931 let mut t = Template::default();
932 assert!(t
933 .parse(r#"{{ if eq true false -}} 2000 {{- end }}"#)
934 .is_ok());
935 let data = Context::from(1);
936 let out = t.execute(&mut w, &data);
937 assert!(out.is_ok());
938 assert_eq!(String::from_utf8(w).unwrap(), "");
939
940 let mut w: Vec<u8> = vec![];
941 let mut t = Template::default();
942 assert!(t
943 .parse(r#"{{ if eq 23.42 23.42 -}} 2000 {{- end }}"#)
944 .is_ok());
945 let data = Context::from(1);
946 let out = t.execute(&mut w, &data);
947 assert!(out.is_ok());
948 assert_eq!(String::from_utf8(w).unwrap(), "2000");
949
950 let mut w: Vec<u8> = vec![];
951 let mut t = Template::default();
952 assert!(t.parse(r#"{{ if eq 1 . -}} 2000 {{- end }}"#).is_ok());
953 let data = Context::from(1);
954 let out = t.execute(&mut w, &data);
955 assert!(out.is_ok());
956 assert_eq!(String::from_utf8(w).unwrap(), "2000");
957 }
958
959 #[test]
960 fn test_block() {
961 let mut w: Vec<u8> = vec![];
962 let mut t = Template::default();
963 assert!(t
964 .parse(r#"{{ block "foobar" true -}} {{ $ }} {{- end }}"#)
965 .is_ok());
966 let data = Context::from(2000);
967 let out = t.execute(&mut w, &data);
968 assert!(out.is_ok());
969 assert_eq!(String::from_utf8(w).unwrap(), "true");
970 }
971
972 #[test]
973 fn test_assign_string() {
974 let mut w: Vec<u8> = vec![];
975 let mut t = Template::default();
976 assert!(t
977 .parse(r#"{{ with $foo := "bar" }}{{ $foo }}{{ end }}"#)
978 .is_ok());
979 let data = Context::from(1);
980 let out = t.execute(&mut w, &data);
981 assert!(out.is_ok());
982 assert_eq!(String::from_utf8(w).unwrap(), "bar");
983 }
984}