difftreelog
perf cheaper error formatting where possible
in: master
3 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth378 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}384384385#[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}391391crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth84pub 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::*;crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth7 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};1313678 })678 })679}679}680681struct 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();689690 while input.peek(Token![,]) {691 input.parse::<Token![,]>()?;692 if input.is_empty() {693 // Trailing comma694 break;695 }696 let expr = input.parse()?;697 arguments.push(expr);698 }699700 if !input.is_empty() {701 return Err(syn::Error::new(input.span(), "unexpected trailing input"));702 }703704 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 != 0745}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}768769/// IStr formatting helper770///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 uses773/// `format!()` only when necessary774#[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