liquid_compiler/
filter_chain.rs

1use std::fmt;
2use std::io::Write;
3
4use itertools;
5
6use super::Filter;
7use liquid_error::{Result, ResultLiquidExt, ResultLiquidReplaceExt};
8use liquid_interpreter::Context;
9use liquid_interpreter::Expression;
10use liquid_interpreter::Renderable;
11use liquid_value::Value;
12
13/// A `Value` expression.
14#[derive(Debug)]
15pub struct FilterChain {
16    entry: Expression,
17    filters: Vec<Box<Filter>>,
18}
19
20impl FilterChain {
21    /// Create a new expression.
22    pub fn new(entry: Expression, filters: Vec<Box<Filter>>) -> Self {
23        Self { entry, filters }
24    }
25
26    /// Process `Value` expression within `context`'s stack.
27    pub fn evaluate(&self, context: &Context) -> Result<Value> {
28        // take either the provided value or the value from the provided variable
29        let mut entry = self.entry.evaluate(context)?.to_owned();
30
31        // apply all specified filters
32        for filter in &self.filters {
33            entry = filter
34                .evaluate(&entry, context)
35                .trace("Filter error")
36                .context_key("filter")
37                .value_with(|| format!("{}", filter).into())
38                .context_key("input")
39                .value_with(|| format!("{}", entry.source()).into())?;
40        }
41
42        Ok(entry)
43    }
44}
45
46impl fmt::Display for FilterChain {
47    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
48        write!(
49            f,
50            "{} | {}",
51            self.entry,
52            itertools::join(&self.filters, " | ")
53        )
54    }
55}
56
57impl Renderable for FilterChain {
58    fn render_to(&self, writer: &mut Write, context: &mut Context) -> Result<()> {
59        let entry = self.evaluate(context)?;
60        write!(writer, "{}", entry.to_str()).replace("Failed to render")?;
61        Ok(())
62    }
63}