From 6aeda8b237fcbf7a56ca0e8c0fff415477d31d22 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 18 Aug 2026 01:57:02 +0900 Subject: refactor(preg): make preg_match_all yield matches per occurrence PHP's PREG_PATTERN_ORDER is column-oriented, but 7 of the 10 call sites read it row-wise, rebuilding each occurrence by indexing every column at the same offset. Return an iterator of PregMatches instead, which is also what the set-order and offset-capture variants were carrying, so the three functions collapse into one and PregMatchesAll, PregMatchesAllWithOffsets, CaptureKey and preg_match_map! all go away. The offset-capture call sites are served by the new PregMatches get_offset/name_offset accessors. The search stays eager: regex::Captures borrows only the subject, so the matches outlive the pattern resolved for the call, and PHP's preg_match_all is eager too. Co-Authored-By: Claude Opus 5 (1M context) --- .../shirabe/src/package/version/version_bumper.rs | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'crates/shirabe/src/package/version') diff --git a/crates/shirabe/src/package/version/version_bumper.rs b/crates/shirabe/src/package/version/version_bumper.rs index 075663d4..4bb95ef1 100644 --- a/crates/shirabe/src/package/version/version_bumper.rs +++ b/crates/shirabe/src/package/version/version_bumper.rs @@ -5,9 +5,7 @@ use crate::package::dumper::ArrayDumper; use crate::package::loader::ArrayLoader; use crate::package::version::VersionParser; use crate::util::Platform; -use shirabe_php_shim::{ - CaptureKey, php_regex, preg_is_match, preg_match_all_offset_capture, preg_replace, -}; +use shirabe_php_shim::{php_regex, preg_is_match, preg_match_all, preg_replace}; use shirabe_semver::Intervals; use shirabe_semver::constraint::AnyConstraint; @@ -78,19 +76,21 @@ impl VersionBumper { major = major ); - let matches = preg_match_all_offset_capture(&pattern, &pretty_constraint); - if matches.occurrence_count() > 0 { - let mut modified = pretty_constraint.clone(); - let constraint_matches = matches - .get(&CaptureKey::ByName("constraint".to_string())) - .cloned() - .unwrap_or_default(); - for match_ in constraint_matches.iter().rev() { - let match_str = match_ - .0 - .as_deref() + // Collected eagerly: a match borrows `pretty_constraint`, which the returns below move. + let constraint_matches: Vec<(String, i64)> = preg_match_all(&pattern, &pretty_constraint) + .map(|match_| { + let constraint = match_ + .name("constraint") + .expect("the `constraint` group participates whenever the pattern matches"); + let offset = match_ + .name_offset("constraint") .expect("the `constraint` group participates whenever the pattern matches"); - let match_offset = match_.1; + (constraint.to_string(), offset as i64) + }) + .collect(); + if !constraint_matches.is_empty() { + let mut modified = pretty_constraint.clone(); + for (match_str, match_offset) in constraint_matches.into_iter().rev() { let suffix = if match_str.matches('.').count() == 2 && version_without_suffix.matches('.').count() == 1 { @@ -119,7 +119,7 @@ impl VersionBumper { &modified, &replacement, match_offset, - Some(Platform::strlen(match_str)), + Some(Platform::strlen(&match_str)), ); } -- cgit v1.3.1-4-g156e