From 2287f5db3c12049afd274496a49b223365fb1e89 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Thu, 16 Jul 2026 19:29:51 +0800 Subject: refactor(flag_matcher): replace `vec_string_slice!` with single-pass iteration --- mingling_picker/src/parselib/flag_matcher.rs | 79 ++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 17 deletions(-) (limited to 'mingling_picker/src') diff --git a/mingling_picker/src/parselib/flag_matcher.rs b/mingling_picker/src/parselib/flag_matcher.rs index af890b9..782d0f8 100644 --- a/mingling_picker/src/parselib/flag_matcher.rs +++ b/mingling_picker/src/parselib/flag_matcher.rs @@ -1,7 +1,6 @@ use crate::{ matcher_needed::*, - parselib::{build_possible_flags, get_seeked_first, multi_seek_eq, seek_end_of_options}, - vec_string_slice, + parselib::{build_possible_flags, get_seeked_first, multi_seek_eq}, }; /// `FlagMatcher` is used to match flags in command-line arguments. @@ -19,12 +18,10 @@ impl Matcher for FlagMatcher { arg_info: &PickerArgInfo, ) -> Option { let possible_flags = build_possible_flags(style, arg_info); + let flag_refs: Vec<&str> = possible_flags.iter().map(|s| s.as_str()).collect(); let end_of_options = seek_end_of_options(args, style); - let result = get_seeked_first(multi_seek_eq( - args, - vec_string_slice!(possible_flags), - style.case_sensitive, - )); + + let result = get_seeked_first(multi_seek_eq(args, &flag_refs, style.case_sensitive)); match (end_of_options, result) { (Some(end), Some(current)) if current > end => None, @@ -38,16 +35,64 @@ impl Matcher for FlagMatcher { arg_info: &PickerArgInfo, ) -> Vec { let possible_flags = build_possible_flags(style, arg_info); - let end_of_options = seek_end_of_options(args, style); - let result = multi_seek_eq( - args, - vec_string_slice!(possible_flags), - style.case_sensitive, - ); - - match end_of_options { - Some(end) => result.into_iter().filter(|&idx| idx <= end).collect(), - None => result, + single_pass_match_all(args, style, &possible_flags) + } +} + +/// Single-pass match: finds the `--` marker and matching flags in one iteration. +fn single_pass_match_all( + args: &[MaskedArg], + style: &ParserStyle, + possible_flags: &[String], +) -> Vec { + let flag_refs: Vec<&str> = possible_flags.iter().map(|s| s.as_str()).collect(); + let eoo = style.end_of_options; + let case_sensitive = style.case_sensitive; + + let mut end_pos: Option = None; + let mut matches: Vec = Vec::new(); + + for arg in args { + if end_pos.is_none() { + let is_eoo = if case_sensitive { + arg.raw == eoo + } else { + arg.raw.eq_ignore_ascii_case(eoo) + }; + if is_eoo { + end_pos = Some(arg.raw_idx); + continue; + } + } + + // Only match flags before the end-of-options marker. + if end_pos.is_none() { + let matched = if case_sensitive { + flag_refs.contains(&arg.raw) + } else { + flag_refs.iter().any(|s| arg.raw.eq_ignore_ascii_case(s)) + }; + if matched { + matches.push(arg.raw_idx); + } } } + + matches +} + +/// Locate the end-of-options marker (`--`) in the argument list. +fn seek_end_of_options(args: &[MaskedArg], style: &ParserStyle) -> Option { + get_seeked_first( + args.iter() + .filter(|arg| { + if style.case_sensitive { + arg.raw == style.end_of_options + } else { + arg.raw.eq_ignore_ascii_case(style.end_of_options) + } + }) + .map(|arg| arg.raw_idx) + .collect(), + ) } -- cgit