From f63503bb63cd1ef57746520f1c09681ade2f760b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 13 Sep 2024 12:56:06 +0200 Subject: [PATCH 1/6] derive: in tests, print source if malformed --- rinja_derive/src/tests.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/rinja_derive/src/tests.rs b/rinja_derive/src/tests.rs index 57e36ec44..258bc3cfd 100644 --- a/rinja_derive/src/tests.rs +++ b/rinja_derive/src/tests.rs @@ -21,10 +21,21 @@ struct Foo {{ {} }}"##, .collect::>() .join(","), ); - let generated = build_template(&syn::parse_str::(&jinja).unwrap()) - .unwrap() - .parse() - .unwrap(); + + let generated = build_template(&syn::parse_str::(&jinja).unwrap()).unwrap(); + let generated = match generated.parse() { + Ok(generated) => generated, + Err(err) => panic!( + "\n\ + === Invalid code generated ===\n\ + \n\ + {generated}\n\ + \n\ + === Error ===\n\ + \n\ + {err}" + ), + }; let generated: syn::File = syn::parse2(generated).unwrap(); let size_hint = proc_macro2::Literal::usize_unsuffixed(size_hint); From 75851fa09cd4b17acef8e2b3b5914811e6deffb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 13 Sep 2024 12:56:43 +0200 Subject: [PATCH 2/6] parser: make WithSpan contructor const --- rinja_parser/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rinja_parser/src/lib.rs b/rinja_parser/src/lib.rs index 6033864c0..679ab15e3 100644 --- a/rinja_parser/src/lib.rs +++ b/rinja_parser/src/lib.rs @@ -137,7 +137,7 @@ pub struct WithSpan<'a, T> { } impl<'a, T> WithSpan<'a, T> { - pub fn new(inner: T, span: &'a str) -> Self { + pub const fn new(inner: T, span: &'a str) -> Self { Self { inner, span } } From db45e5ac5156481b4388f25ba6a7de8ba8a7c398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 13 Sep 2024 12:57:46 +0200 Subject: [PATCH 3/6] derive: add `_visit_arg` method --- rinja_derive/src/generator.rs | 72 ++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/rinja_derive/src/generator.rs b/rinja_derive/src/generator.rs index 201b8640d..6469445ad 100644 --- a/rinja_derive/src/generator.rs +++ b/rinja_derive/src/generator.rs @@ -1809,34 +1809,62 @@ impl<'a> Generator<'a> { buf: &mut Buffer, args: &[WithSpan<'_, Expr<'_>>], ) -> Result<(), CompileError> { - if args.is_empty() { - return Ok(()); - } - for (i, arg) in args.iter().enumerate() { if i > 0 { buf.write(','); } + self._visit_arg(ctx, buf, arg)?; + } + Ok(()) + } - let borrow = !is_copyable(arg); - if borrow { - buf.write("&("); + fn _visit_arg( + &mut self, + ctx: &Context<'_>, + buf: &mut Buffer, + arg: &WithSpan<'_, Expr<'_>>, + ) -> Result<(), CompileError> { + let borrow = !is_copyable(arg); + if borrow { + buf.write("&("); + } + match **arg { + Expr::Call(ref left, _) if !matches!(***left, Expr::Path(_)) => { + buf.write('{'); + self.visit_expr(ctx, buf, arg)?; + buf.write('}'); } - - match **arg { - Expr::Call(ref left, _) if !matches!(***left, Expr::Path(_)) => { - buf.write('{'); - self.visit_expr(ctx, buf, arg)?; - buf.write('}'); - } - _ => { - self.visit_expr(ctx, buf, arg)?; - } + _ => { + self.visit_expr(ctx, buf, arg)?; } + } + if borrow { + buf.write(')'); + } + Ok(()) + } - if borrow { + fn _visit_auto_escaped_arg( + &mut self, + ctx: &Context<'_>, + buf: &mut Buffer, + arg: &WithSpan<'_, Expr<'_>>, + ) -> Result<(), CompileError> { + if let Some(Writable::Lit(arg)) = compile_time_escape(arg, self.input.escaper) { + if !arg.is_empty() { + buf.write(format_args!("{CRATE}::filters::Safe(")); + buf.write_escaped_str(&arg); buf.write(')'); + } else { + buf.write(format_args!("{CRATE}::helpers::Empty")); } + } else { + buf.write(format_args!("(&&::rinja::filters::AutoEscaper::new(")); + self._visit_arg(ctx, buf, arg)?; + buf.write(format_args!( + ", {})).rinja_auto_escape()?", + self.input.escaper + )); } Ok(()) } @@ -2436,6 +2464,14 @@ impl Buffer { } } + fn write_escaped_str(&mut self, s: &str) { + if !self.discard { + self.buf.push('"'); + string_escape(&mut self.buf, s); + self.buf.push('"'); + } + } + fn write_writer(&mut self, s: &str) -> usize { const OPEN: &str = r#"writer.write_str(""#; const CLOSE: &str = r#"")?;"#; From 27443641f5defa726d5851b03163cf137ae3daf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 13 Sep 2024 13:24:42 +0200 Subject: [PATCH 4/6] filters: escape arguments to `pluralize` at compile time --- rinja/src/filters/builtin.rs | 25 ++++ rinja/src/helpers.rs | 20 ++++ rinja_derive/src/generator.rs | 101 ++++++++++++++-- rinja_derive/src/tests.rs | 184 ++++++++++++++++++++++++++++++ testing/tests/ui/pluralize.rs | 12 ++ testing/tests/ui/pluralize.stderr | 18 +++ 6 files changed, 352 insertions(+), 8 deletions(-) create mode 100644 testing/tests/ui/pluralize.rs create mode 100644 testing/tests/ui/pluralize.stderr diff --git a/rinja/src/filters/builtin.rs b/rinja/src/filters/builtin.rs index e18c2dfd8..50b9ebe3d 100644 --- a/rinja/src/filters/builtin.rs +++ b/rinja/src/filters/builtin.rs @@ -611,6 +611,31 @@ pub fn title(s: impl fmt::Display) -> Result { /// ); /// # } /// ``` +/// +/// ## Arguments get escaped +/// +/// ``` +/// # #[cfg(feature = "code-in-doc")] { +/// # use rinja::Template; +/// /// ```jinja +/// /// You are number {{ number|pluralize("ONE", number) }}! +/// /// ``` +/// #[derive(Template)] +/// #[template(ext = "html", in_doc = true)] +/// struct Number { +/// number: usize +/// } +/// +/// assert_eq!( +/// Number { number: 1 }.to_string(), +/// "You are number <b>ONE</b>!", +/// ); +/// assert_eq!( +/// Number { number: 9000 }.to_string(), +/// "You are number 9000!", +/// ); +/// # } +/// ``` #[inline] pub fn pluralize(count: C, singular: S, plural: P) -> Result, C::Error> where diff --git a/rinja/src/helpers.rs b/rinja/src/helpers.rs index 719b99f96..5290a9cda 100644 --- a/rinja/src/helpers.rs +++ b/rinja/src/helpers.rs @@ -4,6 +4,8 @@ use std::cell::Cell; use std::fmt; use std::iter::{Enumerate, Peekable}; +use crate::filters::FastWritable; + pub struct TemplateLoop where I: Iterator, @@ -128,3 +130,21 @@ primitive_type! { i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, } + +/// An empty element, so nothing will be written. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Empty; + +impl fmt::Display for Empty { + #[inline] + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + Ok(()) + } +} + +impl FastWritable for Empty { + #[inline] + fn write_into(&self, _: &mut W) -> fmt::Result { + Ok(()) + } +} diff --git a/rinja_derive/src/generator.rs b/rinja_derive/src/generator.rs index 6469445ad..a902ad44e 100644 --- a/rinja_derive/src/generator.rs +++ b/rinja_derive/src/generator.rs @@ -1564,20 +1564,44 @@ impl<'a> Generator<'a> { args: &[WithSpan<'_, Expr<'_>>], node: &WithSpan<'_, T>, ) -> Result { - buf.write(format_args!("{CRATE}::filters::pluralize(")); - self._visit_args(ctx, buf, args)?; - match args.len() { - 1 => buf.write(r#", "", "s""#), - 2 => buf.write(r#", "s""#), - 3 => {} + const SINGULAR: &WithSpan<'static, Expr<'static>> = &WithSpan::new( + Expr::StrLit(StrLit { + prefix: None, + content: "", + }), + "", + ); + const PLURAL: &WithSpan<'static, Expr<'static>> = &WithSpan::new( + Expr::StrLit(StrLit { + prefix: None, + content: "s", + }), + "", + ); + + let (count, sg, pl) = match args { + [count] => (count, SINGULAR, PLURAL), + [count, sg] => (count, sg, PLURAL), + [count, sg, pl] => (count, sg, pl), _ => { return Err( ctx.generate_error("unexpected argument(s) in `pluralize` filter", node) ); } + }; + if let Some(is_singular) = expr_is_int_lit_plus_minus_one(count) { + let value = if is_singular { sg } else { pl }; + self._visit_auto_escaped_arg(ctx, buf, value)?; + } else { + buf.write(format_args!("{CRATE}::filters::pluralize(")); + self._visit_arg(ctx, buf, count)?; + for value in [sg, pl] { + buf.write(", "); + self._visit_auto_escaped_arg(ctx, buf, value)?; + } + buf.write(format_args!(")?")); } - buf.write(")?"); - Ok(DisplayWrap::Unwrapped) + Ok(DisplayWrap::Wrapped) } fn _visit_linebreaks_filter( @@ -2293,6 +2317,67 @@ impl<'a> Generator<'a> { } } +fn expr_is_int_lit_plus_minus_one(expr: &WithSpan<'_, Expr<'_>>) -> Option { + fn is_signed_singular( + from_str_radix: impl Fn(&str, u32) -> Result, + value: &str, + plus_one: T, + minus_one: T, + ) -> Option { + Some([plus_one, minus_one].contains(&from_str_radix(value, 10).ok()?)) + } + + fn is_unsigned_singular( + from_str_radix: impl Fn(&str, u32) -> Result, + value: &str, + plus_one: T, + ) -> Option { + Some(from_str_radix(value, 10).ok()? == plus_one) + } + + let Expr::NumLit(_, Num::Int(value, kind)) = **expr else { + return None; + }; + match kind { + Some(IntKind::I8) => is_signed_singular(i8::from_str_radix, value, 1, -1), + Some(IntKind::I16) => is_signed_singular(i16::from_str_radix, value, 1, -1), + Some(IntKind::I32) => is_signed_singular(i32::from_str_radix, value, 1, -1), + Some(IntKind::I64) => is_signed_singular(i64::from_str_radix, value, 1, -1), + Some(IntKind::I128) => is_signed_singular(i128::from_str_radix, value, 1, -1), + Some(IntKind::Isize) => { + if cfg!(target_pointer_width = "16") { + is_signed_singular(i16::from_str_radix, value, 1, -1) + } else if cfg!(target_pointer_width = "32") { + is_signed_singular(i32::from_str_radix, value, 1, -1) + } else if cfg!(target_pointer_width = "64") { + is_signed_singular(i64::from_str_radix, value, 1, -1) + } else { + unreachable!("unexpected `cfg!(target_pointer_width)`") + } + } + Some(IntKind::U8) => is_unsigned_singular(u8::from_str_radix, value, 1), + Some(IntKind::U16) => is_unsigned_singular(u16::from_str_radix, value, 1), + Some(IntKind::U32) => is_unsigned_singular(u32::from_str_radix, value, 1), + Some(IntKind::U64) => is_unsigned_singular(u64::from_str_radix, value, 1), + Some(IntKind::U128) => is_unsigned_singular(u128::from_str_radix, value, 1), + Some(IntKind::Usize) => { + if cfg!(target_pointer_width = "16") { + is_unsigned_singular(u16::from_str_radix, value, 1) + } else if cfg!(target_pointer_width = "32") { + is_unsigned_singular(u32::from_str_radix, value, 1) + } else if cfg!(target_pointer_width = "64") { + is_unsigned_singular(u64::from_str_radix, value, 1) + } else { + unreachable!("unexpected `cfg!(target_pointer_width)`") + } + } + None => match value.starts_with('-') { + true => is_signed_singular(i128::from_str_radix, value, 1, -1), + false => is_unsigned_singular(u128::from_str_radix, value, 1), + }, + } +} + /// In here, we inspect in the expression if it is a literal, and if it is, whether it /// can be escaped at compile time. fn compile_time_escape<'a>(expr: &Expr<'a>, escaper: &str) -> Option> { diff --git a/rinja_derive/src/tests.rs b/rinja_derive/src/tests.rs index 258bc3cfd..ce957cebe 100644 --- a/rinja_derive/src/tests.rs +++ b/rinja_derive/src/tests.rs @@ -731,3 +731,187 @@ fn test_code_in_comment() { let generated = build_template(&ast).unwrap(); assert!(!generated.contains("compile_error")); } + +#[test] +fn test_pluralize() { + compare( + r#"{{dogs}} dog{{dogs|pluralize}}"#, + r#" + match ( + &((&&::rinja::filters::AutoEscaper::new( + &(self.dogs), + ::rinja::filters::Text, + )) + .rinja_auto_escape()?), + &(::rinja::filters::pluralize( + &(self.dogs), + ::rinja::helpers::Empty, + ::rinja::filters::Safe("s"), + )?), + ) { + (expr0, expr3) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + writer.write_str(" dog")?; + (&&::rinja::filters::Writable(expr3)).rinja_write(writer)?; + } + }"#, + &[("dogs", "i8")], + 10, + ); + compare( + r#"{{dogs}} dog{{dogs|pluralize("go")}}"#, + r#" + match ( + &((&&::rinja::filters::AutoEscaper::new( + &(self.dogs), + ::rinja::filters::Text, + )) + .rinja_auto_escape()?), + &(::rinja::filters::pluralize( + &(self.dogs), + ::rinja::filters::Safe("go"), + ::rinja::filters::Safe("s"), + )?), + ) { + (expr0, expr3) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + writer.write_str(" dog")?; + (&&::rinja::filters::Writable(expr3)).rinja_write(writer)?; + } + }"#, + &[("dogs", "i8")], + 10, + ); + compare( + r#"{{mice}} {{mice|pluralize("mouse", "mice")}}"#, + r#" + match ( + &((&&::rinja::filters::AutoEscaper::new( + &(self.mice), + ::rinja::filters::Text, + )) + .rinja_auto_escape()?), + &(::rinja::filters::pluralize( + &(self.mice), + ::rinja::filters::Safe("mouse"), + ::rinja::filters::Safe("mice"), + )?), + ) { + (expr0, expr2) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + writer.write_str(" ")?; + (&&::rinja::filters::Writable(expr2)).rinja_write(writer)?; + } + }"#, + &[("dogs", "i8")], + 7, + ); + + compare( + r#"{{count|pluralize(one, count)}}"#, + r#" + match ( + &(::rinja::filters::pluralize( + &(self.count), + (&&::rinja::filters::AutoEscaper::new( + &(self.one), + ::rinja::filters::Text, + )) + .rinja_auto_escape()?, + (&&::rinja::filters::AutoEscaper::new( + &(self.count), + ::rinja::filters::Text, + )) + .rinja_auto_escape()?, + )?), + ) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[("count", "i8"), ("one", "&'static str")], + 3, + ); + + compare( + r#"{{0|pluralize(sg, pl)}}"#, + r#" + match ( + &((&&::rinja::filters::AutoEscaper::new(&(self.pl), ::rinja::filters::Text)) + .rinja_auto_escape()?), + ) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[("sg", "&'static str"), ("pl", "&'static str")], + 3, + ); + compare( + r#"{{1|pluralize(sg, pl)}}"#, + r#" + match ( + &((&&::rinja::filters::AutoEscaper::new(&(self.sg), ::rinja::filters::Text)) + .rinja_auto_escape()?), + ) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[("sg", "&'static str"), ("pl", "&'static str")], + 3, + ); + + compare( + r#"{{0|pluralize("sg", "pl")}}"#, + r#" + match (&(::rinja::filters::Safe("pl")),) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[], + 3, + ); + compare( + r#"{{1|pluralize("sg", "pl")}}"#, + r#" + match (&(::rinja::filters::Safe("sg")),) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[], + 3, + ); + + compare( + r#"{{0|pluralize}}"#, + r#" + match (&(::rinja::filters::Safe("s")),) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[], + 3, + ); + compare( + r#"{{1|pluralize}}"#, + r#" + match (&(::rinja::helpers::Empty),) { + (expr0,) => { + (&&::rinja::filters::Writable(expr0)).rinja_write(writer)?; + } + } + "#, + &[], + 3, + ); +} diff --git a/testing/tests/ui/pluralize.rs b/testing/tests/ui/pluralize.rs new file mode 100644 index 000000000..250189d83 --- /dev/null +++ b/testing/tests/ui/pluralize.rs @@ -0,0 +1,12 @@ +use rinja::Template; + +#[derive(Template)] +#[template( + ext = "html", + source = "{{ input|pluralize }}", +)] +struct Pluralize { + input: &'static str, +} + +fn main() {} diff --git a/testing/tests/ui/pluralize.stderr b/testing/tests/ui/pluralize.stderr new file mode 100644 index 000000000..1df47d9db --- /dev/null +++ b/testing/tests/ui/pluralize.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `str: PluralizeCount` is not satisfied + --> tests/ui/pluralize.rs:3:10 + | +3 | #[derive(Template)] + | ^^^^^^^^ the trait `PluralizeCount` is not implemented for `str`, which is required by `&str: PluralizeCount` + | + = help: the following other types implement trait `PluralizeCount`: + &T + Arc + Box + MutexGuard<'_, T> + NonZero + NonZero + NonZero + NonZero + and $N others + = note: required for `&str` to implement `PluralizeCount` + = note: this error originates in the derive macro `Template` (in Nightly builds, run with -Z macro-backtrace for more info) From a0c972923daa70a68e4b6239969636572ed9ded1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 13 Sep 2024 17:50:42 +0200 Subject: [PATCH 5/6] generator: use macro to implement `expr_is_int_lit_plus_minus_one()` --- rinja_derive/src/generator.rs | 119 +++++++++++++++++----------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/rinja_derive/src/generator.rs b/rinja_derive/src/generator.rs index a902ad44e..385644e36 100644 --- a/rinja_derive/src/generator.rs +++ b/rinja_derive/src/generator.rs @@ -2317,6 +2317,29 @@ impl<'a> Generator<'a> { } } +#[cfg(target_pointer_width = "16")] +type TargetIsize = i16; +#[cfg(target_pointer_width = "32")] +type TargetIsize = i32; +#[cfg(target_pointer_width = "64")] +type TargetIsize = i64; + +#[cfg(target_pointer_width = "16")] +type TargetUsize = u16; +#[cfg(target_pointer_width = "32")] +type TargetUsize = u32; +#[cfg(target_pointer_width = "64")] +type TargetUsize = u64; + +#[cfg(not(any( + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64" +)))] +const _: () = { + panic!("unknown cfg!(target_pointer_width)"); +}; + fn expr_is_int_lit_plus_minus_one(expr: &WithSpan<'_, Expr<'_>>) -> Option { fn is_signed_singular( from_str_radix: impl Fn(&str, u32) -> Result, @@ -2335,46 +2358,44 @@ fn expr_is_int_lit_plus_minus_one(expr: &WithSpan<'_, Expr<'_>>) -> Option Some(from_str_radix(value, 10).ok()? == plus_one) } + macro_rules! impl_match { + ( + $kind:ident $value:ident; + $($svar:ident => $sty:ident),*; + $($uvar:ident => $uty:ident),*; + ) => { + match $kind { + $( + Some(IntKind::$svar) => is_signed_singular($sty::from_str_radix, $value, 1, -1), + )* + $( + Some(IntKind::$uvar) => is_unsigned_singular($sty::from_str_radix, $value, 1), + )* + None => match $value.starts_with('-') { + true => is_signed_singular(i128::from_str_radix, $value, 1, -1), + false => is_unsigned_singular(u128::from_str_radix, $value, 1), + }, + } + }; + } + let Expr::NumLit(_, Num::Int(value, kind)) = **expr else { return None; }; - match kind { - Some(IntKind::I8) => is_signed_singular(i8::from_str_radix, value, 1, -1), - Some(IntKind::I16) => is_signed_singular(i16::from_str_radix, value, 1, -1), - Some(IntKind::I32) => is_signed_singular(i32::from_str_radix, value, 1, -1), - Some(IntKind::I64) => is_signed_singular(i64::from_str_radix, value, 1, -1), - Some(IntKind::I128) => is_signed_singular(i128::from_str_radix, value, 1, -1), - Some(IntKind::Isize) => { - if cfg!(target_pointer_width = "16") { - is_signed_singular(i16::from_str_radix, value, 1, -1) - } else if cfg!(target_pointer_width = "32") { - is_signed_singular(i32::from_str_radix, value, 1, -1) - } else if cfg!(target_pointer_width = "64") { - is_signed_singular(i64::from_str_radix, value, 1, -1) - } else { - unreachable!("unexpected `cfg!(target_pointer_width)`") - } - } - Some(IntKind::U8) => is_unsigned_singular(u8::from_str_radix, value, 1), - Some(IntKind::U16) => is_unsigned_singular(u16::from_str_radix, value, 1), - Some(IntKind::U32) => is_unsigned_singular(u32::from_str_radix, value, 1), - Some(IntKind::U64) => is_unsigned_singular(u64::from_str_radix, value, 1), - Some(IntKind::U128) => is_unsigned_singular(u128::from_str_radix, value, 1), - Some(IntKind::Usize) => { - if cfg!(target_pointer_width = "16") { - is_unsigned_singular(u16::from_str_radix, value, 1) - } else if cfg!(target_pointer_width = "32") { - is_unsigned_singular(u32::from_str_radix, value, 1) - } else if cfg!(target_pointer_width = "64") { - is_unsigned_singular(u64::from_str_radix, value, 1) - } else { - unreachable!("unexpected `cfg!(target_pointer_width)`") - } - } - None => match value.starts_with('-') { - true => is_signed_singular(i128::from_str_radix, value, 1, -1), - false => is_unsigned_singular(u128::from_str_radix, value, 1), - }, + impl_match! { + kind value; + I8 => i8, + I16 => i16, + I32 => i32, + I64 => i64, + I128 => i128, + Isize => TargetIsize; + U8 => u8, + U16 => u16, + U32 => u32, + U64 => u64, + U128 => u128, + Usize => TargetUsize; } } @@ -2454,33 +2475,13 @@ fn compile_time_escape<'a>(expr: &Expr<'a>, escaper: &str) -> Option int(i32::from_str_radix, &value)?, NumKind::Int(Some(IntKind::I64)) => int(i64::from_str_radix, &value)?, NumKind::Int(Some(IntKind::I128)) => int(i128::from_str_radix, &value)?, - NumKind::Int(Some(IntKind::Isize)) => { - if cfg!(target_pointer_width = "16") { - int(i16::from_str_radix, &value)? - } else if cfg!(target_pointer_width = "32") { - int(i32::from_str_radix, &value)? - } else if cfg!(target_pointer_width = "64") { - int(i64::from_str_radix, &value)? - } else { - unreachable!("unexpected `cfg!(target_pointer_width)`") - } - } + NumKind::Int(Some(IntKind::Isize)) => int(TargetIsize::from_str_radix, &value)?, NumKind::Int(Some(IntKind::U8)) => int(u8::from_str_radix, &value)?, NumKind::Int(Some(IntKind::U16)) => int(u16::from_str_radix, &value)?, NumKind::Int(Some(IntKind::U32)) => int(u32::from_str_radix, &value)?, NumKind::Int(Some(IntKind::U64)) => int(u64::from_str_radix, &value)?, NumKind::Int(Some(IntKind::U128)) => int(u128::from_str_radix, &value)?, - NumKind::Int(Some(IntKind::Usize)) => { - if cfg!(target_pointer_width = "16") { - int(u16::from_str_radix, &value)? - } else if cfg!(target_pointer_width = "32") { - int(u32::from_str_radix, &value)? - } else if cfg!(target_pointer_width = "64") { - int(u64::from_str_radix, &value)? - } else { - unreachable!("unexpected `cfg!(target_pointer_width)`") - } - } + NumKind::Int(Some(IntKind::Usize)) => int(TargetUsize::from_str_radix, &value)?, NumKind::Int(None) => match value.starts_with('-') { true => int(i128::from_str_radix, &value)?, false => int(u128::from_str_radix, &value)?, From 824b49c1c4d0e23f15905fe62f63668eed37d386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Kijewski?= Date: Fri, 13 Sep 2024 17:52:32 +0200 Subject: [PATCH 6/6] derive: remove useless space --- rinja_derive/src/generator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rinja_derive/src/generator.rs b/rinja_derive/src/generator.rs index 385644e36..3b0a2ff68 100644 --- a/rinja_derive/src/generator.rs +++ b/rinja_derive/src/generator.rs @@ -1596,7 +1596,7 @@ impl<'a> Generator<'a> { buf.write(format_args!("{CRATE}::filters::pluralize(")); self._visit_arg(ctx, buf, count)?; for value in [sg, pl] { - buf.write(", "); + buf.write(','); self._visit_auto_escaped_arg(ctx, buf, value)?; } buf.write(format_args!(")?"));