aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-semver/src/compiling_matcher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-semver/src/compiling_matcher.rs')
-rw-r--r--crates/shirabe-semver/src/compiling_matcher.rs53
1 files changed, 36 insertions, 17 deletions
diff --git a/crates/shirabe-semver/src/compiling_matcher.rs b/crates/shirabe-semver/src/compiling_matcher.rs
index 0d637037..66e9f98c 100644
--- a/crates/shirabe-semver/src/compiling_matcher.rs
+++ b/crates/shirabe-semver/src/compiling_matcher.rs
@@ -4,9 +4,15 @@ use crate::constraint::AnyConstraint;
use crate::constraint::SimpleConstraint;
use indexmap::IndexMap;
use shirabe_php_shim::CmpOp;
+use std::fmt::Write as _;
use std::sync::Mutex;
use std::sync::OnceLock;
+thread_local! {
+ static KEY_BUFFER: std::cell::RefCell<String> =
+ const { std::cell::RefCell::new(String::new()) };
+}
+
// Rust does not support eval(), so the compiled checker path is always disabled.
// The COMPILED_CHECKER_CACHE is retained structurally but never populated.
static COMPILED_CHECKER_CACHE: OnceLock<
@@ -31,28 +37,41 @@ impl CompilingMatcher {
Self::compiled_checker_cache().lock().unwrap().clear();
}
- pub fn r#match(constraint: &AnyConstraint, operator: CmpOp, version: String) -> bool {
- let result_cache_key = format!(
- "{}{};{}",
- SimpleConstraint::get_operator_constant(operator),
- constraint,
- version
- );
+ pub fn r#match(constraint: &AnyConstraint, operator: CmpOp, version: &str) -> bool {
+ #[derive(Debug)]
+ enum CacheResult {
+ Hit(bool),
+ Miss(String),
+ }
+
+ // The key is built into a reused buffer and only copied when it has to be stored, so a
+ // cache hit allocates nothing.
+ let cached = KEY_BUFFER.with_borrow_mut(|key| {
+ key.clear();
+ let _ = write!(
+ key,
+ "{}{};{}",
+ SimpleConstraint::get_operator_constant(operator),
+ constraint,
+ version
+ );
- {
let cache = Self::result_cache().lock().unwrap();
- if let Some(&result) = cache.get(&result_cache_key) {
- return result;
+ match cache.get(key.as_str()) {
+ Some(&result) => CacheResult::Hit(result),
+ None => CacheResult::Miss(key.clone()),
}
- }
+ });
+ let key = match cached {
+ CacheResult::Hit(result) => return result,
+ CacheResult::Miss(key) => key,
+ };
- let result =
- constraint.matches(&SimpleConstraint::new(operator.to_string(), version, None).into());
+ let result = constraint.matches(
+ &SimpleConstraint::new(operator.to_string(), version.to_string(), None).into(),
+ );
- Self::result_cache()
- .lock()
- .unwrap()
- .insert(result_cache_key, result);
+ Self::result_cache().lock().unwrap().insert(key, result);
result
}
}