From 5114a8199a87c9e5584d92848e95deba22b73e98 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 18 Aug 2026 01:56:31 +0900 Subject: refactor(preg): back PregMatches with regex::Captures PregMatches was an IndexMap of owned Strings copied out of the match, so every preg_match2/preg_replace_callback call allocated a String per capture group (twice over for a named group) whether or not the caller read it. It now wraps the regex::Captures itself, held alongside the pattern it came from so groups stay reachable by both their named and their numbered form, and hands out &str borrowed from the subject. The subject's lifetime becomes a parameter of the type. Co-Authored-By: Claude Opus 5 (1M context) --- crates/shirabe/src/command/config_command.rs | 40 +++++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'crates/shirabe/src/command/config_command.rs') diff --git a/crates/shirabe/src/command/config_command.rs b/crates/shirabe/src/command/config_command.rs index 86375f49..35cd2ab6 100644 --- a/crates/shirabe/src/command/config_command.rs +++ b/crates/shirabe/src/command/config_command.rs @@ -1038,7 +1038,7 @@ impl Command for ConfigCommand { .borrow_mut() .as_mut() .unwrap() - .remove_repository(&matches[1]); + .remove_repository(matches.get(&CaptureKey::ByIndex(1)).unwrap()); return Ok(0); } @@ -1052,7 +1052,7 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_repository( - &matches[1], + matches.get(&CaptureKey::ByIndex(1)).unwrap(), PhpMixed::Array(repo), input.borrow().get_option("append")?.as_bool() == Some(true), ); @@ -1072,7 +1072,7 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_repository( - &matches[1], + matches.get(&CaptureKey::ByIndex(1)).unwrap(), PhpMixed::Bool(false), input.borrow().get_option("append")?.as_bool() == Some(true), ); @@ -1086,7 +1086,7 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_repository( - &matches[1], + matches.get(&CaptureKey::ByIndex(1)).unwrap(), value, input.borrow().get_option("append")?.as_bool() == Some(true), ); @@ -1334,18 +1334,30 @@ impl Command for ConfigCommand { .borrow_mut() .as_mut() .unwrap() - .remove_config_setting(&format!("{}.{}", matches[1], matches[2])); + .remove_config_setting(&format!( + "{}.{}", + matches.get(&CaptureKey::ByIndex(1)).unwrap(), + matches.get(&CaptureKey::ByIndex(2)).unwrap() + )); self.config_source .borrow_mut() .as_mut() .unwrap() - .remove_config_setting(&format!("{}.{}", matches[1], matches[2])); + .remove_config_setting(&format!( + "{}.{}", + matches.get(&CaptureKey::ByIndex(1)).unwrap(), + matches.get(&CaptureKey::ByIndex(2)).unwrap() + )); return Ok(0); } - let key = format!("{}.{}", matches[1], matches[2]); - if matches[1] == "bitbucket-oauth" { + let key = format!( + "{}.{}", + matches.get(&CaptureKey::ByIndex(1)).unwrap(), + matches.get(&CaptureKey::ByIndex(2)).unwrap() + ); + if matches.get(&CaptureKey::ByIndex(1)).unwrap() == "bitbucket-oauth" { if 2 != values.len() { return Err(RuntimeException::new(format!( "Expected two arguments (consumer-key, consumer-secret), got {}", @@ -1372,7 +1384,9 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); - } else if matches[1] == "gitlab-token" && 2 == values.len() { + } else if matches.get(&CaptureKey::ByIndex(1)).unwrap() == "gitlab-token" + && 2 == values.len() + { self.config_source .borrow_mut() .as_mut() @@ -1387,7 +1401,7 @@ impl Command for ConfigCommand { .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); } else if matches!( - matches[1].as_str(), + matches.get(&CaptureKey::ByIndex(1)).unwrap().as_str(), "github-oauth" | "gitlab-oauth" | "gitlab-token" | "bearer" ) { if 1 != values.len() { @@ -1406,7 +1420,7 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::String(values[0].clone())); - } else if matches[1] == "http-basic" { + } else if matches.get(&CaptureKey::ByIndex(1)).unwrap() == "http-basic" { if 2 != values.len() { return Err(RuntimeException::new(format!( "Expected two arguments (username, password), got {}", @@ -1427,7 +1441,7 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::Array(obj)); - } else if matches[1] == "custom-headers" { + } else if matches.get(&CaptureKey::ByIndex(1)).unwrap() == "custom-headers" { if values.is_empty() { return Err(RuntimeException::new( "Expected at least one argument (header), got none".to_string(), @@ -1468,7 +1482,7 @@ impl Command for ConfigCommand { .as_mut() .unwrap() .add_config_setting(&key, PhpMixed::List(formatted_headers)); - } else if matches[1] == "forgejo-token" { + } else if matches.get(&CaptureKey::ByIndex(1)).unwrap() == "forgejo-token" { if 2 != values.len() { return Err(RuntimeException::new(format!( "Expected two arguments (username, access token), got {}", -- cgit v1.3.1-4-g156e