#[macro_use] mod jest_macro; pub mod compile; pub mod core; pub mod error; pub mod input; pub mod output; pub mod runtime; pub mod typing; pub use error::{ArithmeticKind, Error, Result}; pub use input::{JestInput, ValueKind}; pub use output::JestOutput; pub use runtime::{ Engine, FloatModel, IntegerModel, Module, ModuleType, Number, NumericTower, OverflowBehavior, Runtime, Value, }; /// Strip `//`-to-end-of-line comments from Jest source, respecting JSON string literals. /// /// A `//` that appears inside a double-quoted string is not treated as a comment. /// Escaped characters (`\"`, `\\`) inside strings are handled correctly. pub fn strip_comments(src: &str) -> String { let mut out = String::with_capacity(src.len()); let mut in_string = false; let mut chars = src.chars().peekable(); while let Some(c) = chars.next() { if in_string { out.push(c); if c == '\\' { // Escaped character: consume next char verbatim. if let Some(escaped) = chars.next() { out.push(escaped); } } else if c == '"' { in_string = false; } } else { match c { '"' => { in_string = true; out.push(c); } '/' if chars.peek() == Some(&'/') => { // Line comment: skip to end of line. for nc in chars.by_ref() { if nc == '\n' { out.push('\n'); break; } } } _ => out.push(c), } } } out } #[cfg(test)] mod tests; /// Evaluate a Jest program (given as a JSON source string) and return the result. pub fn eval(source: &str) -> Result { Runtime::unlimited().run_json(source) } /// Evaluate a Jest program using fast (non-exact) arithmetic. /// i64/f64 only, wrapping overflow, no arbitrary precision. pub fn eval_fast(source: &str) -> Result { Runtime::unlimited().with_engine(Engine::fast()).run_json(source) } /// Evaluate a Jest program with a positional argument list bound to `"args"` in scope. /// /// Both `source` and each element of `args` are JSON text. pub fn eval_with_args(source: &str, args: &[&str]) -> Result { let mut rt = Runtime::unlimited(); let budget = runtime::Budget::new(usize::MAX / 2); let arg_vals: Result> = args .iter() .map(|s| runtime::parse::parse_json(s, &budget)) .collect(); let args_val = Value::array(arg_vals?, &budget)?; let extra = [("args".to_string(), args_val)].into_iter().collect(); let val = runtime::parse::parse_json(source, &budget)?; rt.run_value_with_extra(val, extra) }