Simplify filters handling

This commit is contained in:
Guillaume Gomez 2025-01-22 22:03:05 +01:00
parent 880be8226d
commit 1cf81ba269

View File

@ -256,15 +256,24 @@ impl<'a> Generator<'a, '_> {
"format" => Self::_visit_format_filter, "format" => Self::_visit_format_filter,
"join" => Self::_visit_join_filter, "join" => Self::_visit_join_filter,
"json" | "tojson" => Self::_visit_json_filter, "json" | "tojson" => Self::_visit_json_filter,
"linebreaks" | "linebreaksbr" | "paragraphbreaks" => Self::_visit_linebreaks_filter, "linebreaks" => Self::_visit_linebreaks_filter,
"linebreaksbr" => Self::_visit_linebreaksbr_filter,
"paragraphbreaks" => Self::_visit_paragraphbreaks_filter,
"pluralize" => Self::_visit_pluralize_filter, "pluralize" => Self::_visit_pluralize_filter,
"ref" => Self::_visit_ref_filter, "ref" => Self::_visit_ref_filter,
"safe" => Self::_visit_safe_filter, "safe" => Self::_visit_safe_filter,
"urlencode" | "urlencode_strict" => Self::_visit_urlencode_filter, "urlencode" => Self::_visit_urlencode_filter,
name if BUILTIN_FILTERS.contains(&name) => Self::_visit_builtin_filter, "urlencode_strict" => Self::_visit_urlencode_strict_filter,
_ => Self::_visit_custom_filter, name if BUILTIN_FILTERS.contains(&name) => {
return self._visit_builtin_filter(ctx, buf, name, args, generics, node);
}
_ => return self._visit_custom_filter(ctx, buf, name, args, generics, node),
}; };
filter(self, ctx, buf, name, args, generics, node) if !generics.is_empty() {
Err(ctx.generate_error(format_args!("unexpected generics on filter `{name}`"), node))
} else {
filter(self, ctx, buf, args, node)
}
} }
fn _visit_custom_filter( fn _visit_custom_filter(
@ -294,8 +303,13 @@ impl<'a> Generator<'a, '_> {
name: &str, name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>], generics: &[WithSpan<'_, TyGenerics<'_>>],
_node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
if !generics.is_empty() {
return Err(
ctx.generate_error(format_args!("unexpected generics on filter `{name}`"), node)
);
}
buf.write(format_args!("rinja::filters::{name}")); buf.write(format_args!("rinja::filters::{name}"));
self.visit_call_generics(buf, generics); self.visit_call_generics(buf, generics);
buf.write('('); buf.write('(');
@ -308,12 +322,30 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?; self._visit_urlencode_filter_inner(ctx, buf, "urlencode", args, node)
}
fn _visit_urlencode_strict_filter(
&mut self,
ctx: &Context<'_>,
buf: &mut Buffer,
args: &[WithSpan<'_, Expr<'a>>],
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> {
self._visit_urlencode_filter_inner(ctx, buf, "urlencode_strict", args, node)
}
fn _visit_urlencode_filter_inner(
&mut self,
ctx: &Context<'_>,
buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>],
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> {
if cfg!(not(feature = "urlencode")) { if cfg!(not(feature = "urlencode")) {
return Err(ctx.generate_error( return Err(ctx.generate_error(
format_args!("the `{name}` filter requires the `urlencode` feature to be enabled"), format_args!("the `{name}` filter requires the `urlencode` feature to be enabled"),
@ -334,15 +366,12 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>], _node: Span<'_>,
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
// All filters return numbers, and any default formatted number is HTML safe. // All filters return numbers, and any default formatted number is HTML safe.
buf.write(format_args!( buf.write(format_args!(
"rinja::filters::HtmlSafeOutput(rinja::filters::{name}(\ "rinja::filters::HtmlSafeOutput(rinja::filters::filesizeformat(\
rinja::helpers::get_primitive_value(&(" rinja::helpers::get_primitive_value(&("
)); ));
self._visit_args(ctx, buf, args)?; self._visit_args(ctx, buf, args)?;
@ -354,9 +383,7 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
const SINGULAR: &WithSpan<'static, Expr<'static>> = const SINGULAR: &WithSpan<'static, Expr<'static>> =
@ -370,7 +397,6 @@ impl<'a> Generator<'a, '_> {
content: "s", content: "s",
})); }));
ensure_filter_has_no_generics(ctx, name, generics, node)?;
let (count, sg, pl) = match args { let (count, sg, pl) = match args {
[count] => (count, SINGULAR, PLURAL), [count] => (count, SINGULAR, PLURAL),
[count, sg] => (count, sg, PLURAL), [count, sg] => (count, sg, PLURAL),
@ -396,16 +422,44 @@ impl<'a> Generator<'a, '_> {
Ok(DisplayWrap::Wrapped) Ok(DisplayWrap::Wrapped)
} }
fn _visit_paragraphbreaks_filter(
&mut self,
ctx: &Context<'_>,
buf: &mut Buffer,
args: &[WithSpan<'_, Expr<'a>>],
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> {
self._visit_linebreaks_filters(ctx, buf, "paragraphbreaks", args, node)
}
fn _visit_linebreaksbr_filter(
&mut self,
ctx: &Context<'_>,
buf: &mut Buffer,
args: &[WithSpan<'_, Expr<'a>>],
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> {
self._visit_linebreaks_filters(ctx, buf, "linebreaksbr", args, node)
}
fn _visit_linebreaks_filter( fn _visit_linebreaks_filter(
&mut self,
ctx: &Context<'_>,
buf: &mut Buffer,
args: &[WithSpan<'_, Expr<'a>>],
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> {
self._visit_linebreaks_filters(ctx, buf, "linebreaks", args, node)
}
fn _visit_linebreaks_filters(
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str, name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
ensure_filter_has_feature_alloc(ctx, name, node)?; ensure_filter_has_feature_alloc(ctx, name, node)?;
if args.len() != 1 { if args.len() != 1 {
return Err(ctx.generate_error( return Err(ctx.generate_error(
@ -427,12 +481,9 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
let arg = match args { let arg = match args {
[arg] => arg, [arg] => arg,
_ => return Err(ctx.generate_error("unexpected argument(s) in `as_ref` filter", node)), _ => return Err(ctx.generate_error("unexpected argument(s) in `as_ref` filter", node)),
@ -446,12 +497,9 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
let arg = match args { let arg = match args {
[arg] => arg, [arg] => arg,
_ => return Err(ctx.generate_error("unexpected argument(s) in `deref` filter", node)), _ => return Err(ctx.generate_error("unexpected argument(s) in `deref` filter", node)),
@ -465,9 +513,7 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
if cfg!(not(feature = "serde_json")) { if cfg!(not(feature = "serde_json")) {
@ -476,7 +522,6 @@ impl<'a> Generator<'a, '_> {
node, node,
)); ));
} }
ensure_filter_has_no_generics(ctx, name, generics, node)?;
let filter = match args.len() { let filter = match args.len() {
1 => "json", 1 => "json",
@ -493,12 +538,9 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
if args.len() != 1 { if args.len() != 1 {
return Err(ctx.generate_error("unexpected argument(s) in `safe` filter", node)); return Err(ctx.generate_error("unexpected argument(s) in `safe` filter", node));
} }
@ -512,12 +554,9 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
if args.len() > 2 { if args.len() > 2 {
return Err(ctx.generate_error("only two arguments allowed to escape filter", node)); return Err(ctx.generate_error("only two arguments allowed to escape filter", node));
} }
@ -575,13 +614,10 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?; ensure_filter_has_feature_alloc(ctx, "format", node)?;
ensure_filter_has_feature_alloc(ctx, name, node)?;
if !args.is_empty() { if !args.is_empty() {
if let Expr::StrLit(ref fmt) = *args[0] { if let Expr::StrLit(ref fmt) = *args[0] {
buf.write("rinja::helpers::std::format!("); buf.write("rinja::helpers::std::format!(");
@ -601,13 +637,10 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>, node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?; ensure_filter_has_feature_alloc(ctx, "fmt", node)?;
ensure_filter_has_feature_alloc(ctx, name, node)?;
if let [_, arg2] = args { if let [_, arg2] = args {
if let Expr::StrLit(ref fmt) = **arg2 { if let Expr::StrLit(ref fmt) = **arg2 {
buf.write("rinja::helpers::std::format!("); buf.write("rinja::helpers::std::format!(");
@ -626,12 +659,9 @@ impl<'a> Generator<'a, '_> {
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
buf: &mut Buffer, buf: &mut Buffer,
name: &str,
args: &[WithSpan<'_, Expr<'a>>], args: &[WithSpan<'_, Expr<'a>>],
generics: &[WithSpan<'_, TyGenerics<'_>>], _node: Span<'_>,
node: Span<'_>,
) -> Result<DisplayWrap, CompileError> { ) -> Result<DisplayWrap, CompileError> {
ensure_filter_has_no_generics(ctx, name, generics, node)?;
buf.write("rinja::filters::join((&"); buf.write("rinja::filters::join((&");
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
if i > 0 { if i > 0 {
@ -1144,19 +1174,6 @@ impl<'a> Generator<'a, '_> {
} }
} }
fn ensure_filter_has_no_generics(
ctx: &Context<'_>,
name: &str,
generics: &[WithSpan<'_, TyGenerics<'_>>],
node: Span<'_>,
) -> Result<(), CompileError> {
if generics.is_empty() {
Ok(())
} else {
Err(ctx.generate_error(format_args!("unexpected generics on filter `{name}`"), node))
}
}
fn ensure_filter_has_feature_alloc( fn ensure_filter_has_feature_alloc(
ctx: &Context<'_>, ctx: &Context<'_>,
name: &str, name: &str,