git.delta.rocks / jrsonnet / refs/commits / 218d8ccde140

difftreelog

perf cheaper error formatting where possible

Yaroslav Bolyukin2023-08-13parent: #6d08ea9.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth
378 return Err($w$(::$i)*$({$($tt)*})?.into())378 return Err($w$(::$i)*$({$($tt)*})?.into())
379 };379 };
380 ($l:literal$(, $($tt:tt)*)?) => {380 ($l:literal$(, $($tt:tt)*)?) => {
381 return Err($crate::error::ErrorKind::RuntimeError(format!($l$(, $($tt)*)?).into()).into())381 return Err($crate::error::ErrorKind::RuntimeError($crate::jrsonnet_macros::format_istr!($l$(, $($tt)*)?)).into())
382 };382 };
383}383}
384384
385#[macro_export]385#[macro_export]
386macro_rules! runtime_error {386macro_rules! runtime_error {
387 ($l:literal$(, $($tt:tt)*)?) => {387 ($l:literal$(, $($tt:tt)*)?) => {
388 $crate::error::Error::from($crate::error::ErrorKind::RuntimeError(format!($l$(, $($tt)*)?).into()))388 $crate::error::Error::from($crate::error::ErrorKind::RuntimeError($crate::jrsonnet_macros::format_istr!($l$(, $($tt)*)?)))
389 };389 };
390}390}
391391
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
84pub use import::*;84pub use import::*;
85use jrsonnet_gcmodule::{Cc, Trace};85use jrsonnet_gcmodule::{Cc, Trace};
86pub use jrsonnet_interner::{IBytes, IStr};86pub use jrsonnet_interner::{IBytes, IStr};
87#[doc(hidden)]
88pub use jrsonnet_macros;
87pub use jrsonnet_parser as parser;89pub use jrsonnet_parser as parser;
88use jrsonnet_parser::*;90use jrsonnet_parser::*;
89pub use obj::*;91pub use obj::*;
modifiedcrates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth
7 punctuated::Punctuated,7 punctuated::Punctuated,
8 spanned::Spanned,8 spanned::Spanned,
9 token::{self, Comma},9 token::{self, Comma},
10 Attribute, DeriveInput, Error, FnArg, GenericArgument, Ident, ItemFn, LitStr, Pat, Path,10 Attribute, DeriveInput, Error, Expr, FnArg, GenericArgument, Ident, ItemFn, LitStr, Pat, Path,
11 PathArguments, Result, ReturnType, Token, Type,11 PathArguments, Result, ReturnType, Token, Type,
12};12};
1313
678 })678 })
679}679}
680
681struct FormatInput {
682 formatting: LitStr,
683 arguments: Vec<Expr>,
684}
685impl Parse for FormatInput {
686 fn parse(input: ParseStream) -> Result<Self> {
687 let formatting = input.parse()?;
688 let mut arguments = Vec::new();
689
690 while input.peek(Token![,]) {
691 input.parse::<Token![,]>()?;
692 if input.is_empty() {
693 // Trailing comma
694 break;
695 }
696 let expr = input.parse()?;
697 arguments.push(expr);
698 }
699
700 if !input.is_empty() {
701 return Err(syn::Error::new(input.span(), "unexpected trailing input"));
702 }
703
704 Ok(Self {
705 formatting,
706 arguments,
707 })
708 }
709}
710fn is_format_str(i: &str) -> bool {
711 let mut is_plain = true;
712 // -1 = {
713 // +1 = }
714 let mut is_bracket = 0i8;
715 for ele in i.chars() {
716 match ele {
717 '{' if is_bracket == -1 => {
718 is_bracket = 0;
719 }
720 '}' if is_bracket == -1 => {
721 is_plain = false;
722 break;
723 }
724 '}' if is_bracket == 1 => {
725 is_bracket = 0;
726 }
727 '{' if is_bracket == 1 => {
728 is_plain = false;
729 break;
730 }
731 '{' => {
732 is_bracket = -1;
733 }
734 '}' => {
735 is_bracket = 1;
736 }
737 _ if is_bracket != 0 => {
738 is_plain = false;
739 break;
740 }
741 _ => {}
742 }
743 }
744 !is_plain || is_bracket != 0
745}
746impl FormatInput {
747 fn expand(self) -> TokenStream {
748 let format = self.formatting;
749 if is_format_str(&format.value()) {
750 let args = self.arguments;
751 quote! {
752 ::jrsonnet_evaluator::IStr::from(format!(#format #(, #args)*))
753 }
754 } else {
755 if let Some(first) = self.arguments.first() {
756 return syn::Error::new(
757 first.span(),
758 "string has no formatting codes, it should not have the arguments",
759 )
760 .into_compile_error();
761 }
762 quote! {
763 ::jrsonnet_evaluator::IStr::from(#format)
764 }
765 }
766 }
767}
768
769/// IStr formatting helper
770///
771/// Using `format!("literal with no codes").into()` is slower than just `"literal with no codes".into()`
772/// This macro looks for formatting codes in the input string, and uses
773/// `format!()` only when necessary
774#[proc_macro]
775pub fn format_istr(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
776 let input = parse_macro_input!(input as FormatInput);
777 input.expand().into()
778}
680779