From e8a28a6d2f97efa4bfba5022f1e417a4d1de2f2a Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sat, 7 Feb 2026 17:00:06 +0800 Subject: [PATCH] feat: use ere (compile-time regex compilation) --- Cargo.lock | 41 +++++++++++++++++++++++++++++++++++++++++ nix-js/Cargo.toml | 1 + nix-js/src/bin/repl.rs | 21 +++++++++------------ nix-js/src/value.rs | 12 ++++-------- 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4200f80..c7a7754 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -916,6 +916,40 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "ere" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced253a70c1159bac921dc672edbb5530c35fbca23a7f1b9f03641f39e4172f1" +dependencies = [ + "ere-core", + "ere-macros", +] + +[[package]] +name = "ere-core" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6639aa08d01ec59ec0509e9b79b4e17b953131b053d1a9a6b449150e58c9706d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "thiserror 2.0.17", + "utf8-ranges", +] + +[[package]] +name = "ere-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a41368e568caa1ee19d8dfa943d7f2f3ddabc0d9c0965cc37d76e0146c6b89" +dependencies = [ + "ere-core", + "quote", + "syn", +] + [[package]] name = "errno" version = "0.3.13" @@ -1912,6 +1946,7 @@ dependencies = [ "deno_error", "derive_more", "dirs", + "ere", "flate2", "hashbrown 0.16.1", "hex", @@ -3550,6 +3585,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf8-ranges" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" + [[package]] name = "utf8_iter" version = "1.0.4" diff --git a/nix-js/Cargo.toml b/nix-js/Cargo.toml index c9f5f31..81651a4 100644 --- a/nix-js/Cargo.toml +++ b/nix-js/Cargo.toml @@ -62,6 +62,7 @@ rnix = "0.12" rowan = "0.15" nix-js-macros = { path = "../nix-js-macros" } +ere = "0.2.4" [dev-dependencies] criterion = { version = "0.5", features = ["html_reports"] } diff --git a/nix-js/src/bin/repl.rs b/nix-js/src/bin/repl.rs index 2217df8..a53daa3 100644 --- a/nix-js/src/bin/repl.rs +++ b/nix-js/src/bin/repl.rs @@ -1,7 +1,6 @@ use anyhow::Result; use nix_js::context::Context; use nix_js::error::Source; -use regex::Regex; use rustyline::DefaultEditor; use rustyline::error::ReadlineError; @@ -10,7 +9,7 @@ fn main() -> Result<()> { let mut rl = DefaultEditor::new()?; let mut context = Context::new()?; - let re = Regex::new(r"^\s*([a-zA-Z_][a-zA-Z0-9_'-]*)\s*=(.*)$").unwrap(); + const RE: ere::Regex<3> = ere::compile_regex!("^[ \t]*([a-zA-Z_][a-zA-Z0-9_'-]*)[ \t]*(.*)$"); loop { let readline = rl.readline("nix-js-repl> "); match readline { @@ -19,18 +18,16 @@ fn main() -> Result<()> { continue; } let _ = rl.add_history_entry(line.as_str()); - if let Some(_caps) = re.captures(&line) { + if let Some([Some(_), Some(_ident), Some(_expr)]) = RE.exec(&line) { eprintln!("Error: binding not implemented yet"); continue; - /* let ident = caps.get(1).unwrap().as_str(); - let expr = caps.get(2).unwrap().as_str().trim(); - if expr.is_empty() { - eprintln!("Error: missing expression after '='"); - continue; - } - if let Err(err) = context.add_binding(ident, expr) { - eprintln!("Error: {}", err); - } */ + // if expr.is_empty() { + // eprintln!("Error: missing expression after '='"); + // continue; + // } + // if let Err(err) = context.add_binding(ident, expr) { + // eprintln!("Error: {}", err); + // } } else { let src = Source::new_repl(line)?; match context.eval_shallow(src) { diff --git a/nix-js/src/value.rs b/nix-js/src/value.rs index 12cdf67..9165704 100644 --- a/nix-js/src/value.rs +++ b/nix-js/src/value.rs @@ -5,10 +5,8 @@ use core::ops::Deref; use std::borrow::Cow; use std::collections::BTreeMap; use std::ops::DerefMut; -use std::sync::LazyLock; use derive_more::{Constructor, IsVariant, Unwrap}; -use regex::Regex; /// Represents a Nix symbol, which is used as a key in attribute sets. #[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Constructor)] @@ -23,10 +21,10 @@ impl> From for Symbol { /// Formats a string slice as a Nix symbol, quoting it if necessary. pub fn format_symbol<'a>(sym: impl Into>) -> Cow<'a, str> { let sym = sym.into(); - if REGEX.is_match(&sym) { + if Symbol::NORMAL_REGEX.test(&sym) { sym } else { - Cow::Owned(format!(r#""{sym}""#)) + Cow::Owned(escape_quote_string(&sym)) } } @@ -40,13 +38,11 @@ impl Display for Symbol { } } -static REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"^[a-zA-Z_][a-zA-Z0-9_'-]*$").expect("hardcoded regex is always valid") -}); impl Symbol { + const NORMAL_REGEX: ere::Regex<1> = ere::compile_regex!("^[a-zA-Z_][a-zA-Z0-9_'-]*$"); /// Checks if the symbol is a "normal" identifier that doesn't require quotes. fn normal(&self) -> bool { - REGEX.is_match(self) + Self::NORMAL_REGEX.test(self) } }