From 0568effc7d92fdc9c3358b153c82bd1c5ef25ea4 Mon Sep 17 00:00:00 2001 From: Leandro Casuso Montero Date: Tue, 29 Nov 2022 15:13:58 -0500 Subject: [PATCH] Removing static compile method; use runtime instances instead --- jmespath-cli/src/main.rs | 10 +++++--- jmespath/benches/generated.rs | 2 +- jmespath/src/lib.rs | 47 ++++++++++++----------------------- jmespath/tests/compliance.rs | 24 ++++++++++-------- 4 files changed, 36 insertions(+), 47 deletions(-) diff --git a/jmespath-cli/src/main.rs b/jmespath-cli/src/main.rs index cbba0ea5..5f664622 100644 --- a/jmespath-cli/src/main.rs +++ b/jmespath-cli/src/main.rs @@ -5,8 +5,8 @@ use std::process::exit; use std::rc::Rc; use clap::{App, Arg}; -use jmespath::Rcvar; -use jmespath::{compile, Variable}; +use jmespath::{Rcvar}; +use jmespath::{Variable}; macro_rules! die( ($msg:expr) => ( @@ -66,10 +66,12 @@ fn main() { .value_of("expr-file") .map(|f| read_file("expression", f)); + let runtime = jmespath::create_default_runtime(); + let expr = if let Some(ref e) = file_expression { - compile(e) + runtime.compile(e) } else { - compile(matches.value_of("expression").unwrap()) + runtime.compile(matches.value_of("expression").unwrap()) } .map_err(|e| die!(e.to_string())) .unwrap(); diff --git a/jmespath/benches/generated.rs b/jmespath/benches/generated.rs index 27db9f82..7092fff9 100644 --- a/jmespath/benches/generated.rs +++ b/jmespath/benches/generated.rs @@ -5,6 +5,6 @@ //extern crate bencher; use bencher::*; -use jmespath::{compile, parse, Rcvar, Variable}; +use jmespath::{parse, Rcvar, Variable}; include!(concat!(env!("OUT_DIR"), "/benches.rs")); diff --git a/jmespath/src/lib.rs b/jmespath/src/lib.rs index 4c67c053..f2a9b1ee 100644 --- a/jmespath/src/lib.rs +++ b/jmespath/src/lib.rs @@ -61,11 +61,7 @@ //! # Custom Functions //! //! You can register custom functions with a JMESPath expression by using -//! a custom `Runtime`. When you call `jmespath::compile`, you are using a -//! shared `Runtime` instance that is created lazily using `lazy_static`. -//! This shared `Runtime` utilizes all of the builtin JMESPath functions -//! by default. However, custom functions may be utilized by creating a custom -//! `Runtime` and compiling expressions directly from the `Runtime`. +//! a custom `Runtime`. //! //! ``` //! use jmespath::{Runtime, Context, Rcvar}; @@ -109,8 +105,6 @@ use serde_json::Value; use std::convert::TryInto; use std::fmt; -use lazy_static::*; - use crate::ast::Ast; use crate::interpreter::{interpret, SearchResult}; @@ -121,12 +115,10 @@ mod parser; mod runtime; mod variable; -lazy_static! { - pub static ref DEFAULT_RUNTIME: Runtime = { - let mut runtime = Runtime::new(); - runtime.register_builtin_functions(); - runtime - }; +pub fn create_default_runtime() -> Runtime { + let mut runtime = Runtime::new(); + runtime.register_builtin_functions(); + runtime } /// `Rc` reference counted JMESPath `Variable`. @@ -136,18 +128,6 @@ pub type Rcvar = std::rc::Rc; #[cfg(feature = "sync")] pub type Rcvar = std::sync::Arc; -/// Compiles a JMESPath expression using the default Runtime. -/// -/// The default Runtime is created lazily the first time it is dereferenced -/// by using the `lazy_static` macro. -/// -/// The provided expression is expected to adhere to the JMESPath -/// grammar: -#[inline] -pub fn compile(expression: &str) -> Result, JmespathError> { - DEFAULT_RUNTIME.compile(expression) -} - /// Converts a value into a reference-counted JMESPath Variable. /// #[cfg_attr( @@ -466,27 +446,31 @@ mod test { #[test] fn formats_expression_as_string_or_debug() { - let expr = compile("foo | baz").unwrap(); + let runtime = create_default_runtime(); + let expr = runtime.compile("foo | baz").unwrap(); assert_eq!("foo | baz/foo | baz", format!("{}/{:?}", expr, expr)); } #[test] fn implements_partial_eq() { - let a = compile("@").unwrap(); - let b = compile("@").unwrap(); + let runtime = create_default_runtime(); + let a = runtime.compile("@").unwrap(); + let b = runtime.compile("@").unwrap(); assert!(a == b); } #[test] fn can_evaluate_jmespath_expression() { - let expr = compile("foo.bar").unwrap(); + let runtime = create_default_runtime(); + let expr = runtime.compile("foo.bar").unwrap(); let var = Variable::from_json("{\"foo\":{\"bar\":true}}").unwrap(); assert_eq!(Rcvar::new(Variable::Bool(true)), expr.search(var).unwrap()); } #[test] fn can_get_expression_ast() { - let expr = compile("foo").unwrap(); + let runtime = create_default_runtime(); + let expr = runtime.compile("foo").unwrap(); assert_eq!( &Ast::Field { offset: 0, @@ -505,7 +489,8 @@ mod test { #[test] fn expression_clone() { - let expr = compile("foo").unwrap(); + let runtime = create_default_runtime(); + let expr = runtime.compile("foo").unwrap(); let _ = expr.clone(); } } diff --git a/jmespath/tests/compliance.rs b/jmespath/tests/compliance.rs index 1175353b..371a1e06 100644 --- a/jmespath/tests/compliance.rs +++ b/jmespath/tests/compliance.rs @@ -6,7 +6,7 @@ use serde_json::Value; use std::fmt; -use jmespath::{compile, Expression, Rcvar, RuntimeError, Variable}; +use jmespath::{Expression, Rcvar, RuntimeError, Variable, Runtime}; /// Avaliable benchmark types. pub enum BenchType { @@ -101,10 +101,16 @@ pub enum Assertion { impl Assertion { /// Runs the assertion of a test case pub fn assert(&self, suite: &str, case: &TestCase, given: Rcvar) -> Result<(), String> { + let runtime = jmespath::create_default_runtime(); + match self { &Assertion::Bench(_) => Ok(()), &Assertion::ValidResult(ref expected_result) => { - let expr = self.try_parse(suite, case)?; + let expr = match runtime.compile(&case.expression) { + Err(e) => Err(self.err_message(suite, case, format!("{}", e))), + Ok(expr) => Ok(expr), + }?; + match expr.search(given) { Err(e) => Err(self.err_message(suite, case, format!("{}", e))), Ok(r) => { @@ -122,7 +128,11 @@ impl Assertion { } &Assertion::Error(ref error_type) => { use jmespath::ErrorReason::*; - let result = self.try_parse(suite, case); + let result = match runtime.compile(&case.expression) { + Err(e) => Err(self.err_message(suite, case, format!("{}", e))), + Ok(expr) => Ok(expr), + }; + match error_type { &ErrorType::InvalidArity => match result?.search(given).map_err(|e| e.reason) { Err(Runtime(RuntimeError::NotEnoughArguments { .. })) => Ok(()), @@ -159,14 +169,6 @@ impl Assertion { } } - /// Attempts to parse an expression for a case, returning the expression or an error string. - fn try_parse(&self, suite: &str, case: &TestCase) -> Result, String> { - match compile(&case.expression) { - Err(e) => Err(self.err_message(suite, case, format!("{}", e))), - Ok(expr) => Ok(expr), - } - } - /// Formats an error message for a test case failure. fn err_message(&self, suite: &str, case: &TestCase, message: String) -> String { format!(