Skip to content

Commit 100d0ea

Browse files
committed
refactor(validate): replace slice const with is_rejected_unicode() fn using matches!
Switch from a REJECTED_UNICODE_CHARS &[char] constant + .contains() (O(M) linear scan per character) to an is_rejected_unicode(c: char) -> bool helper that uses the matches! macro with char ranges. This gives O(1) per character and reads more clearly at call sites via .any(is_rejected_unicode).
1 parent 050d753 commit 100d0ea

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

src/validate.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,24 @@
2121
use crate::error::GwsError;
2222
use std::path::{Path, PathBuf};
2323

24-
/// Dangerous Unicode characters not caught by ASCII-range or `is_control()` checks:
25-
/// zero-width chars, bidi overrides, Unicode line/paragraph separators.
26-
const REJECTED_UNICODE_CHARS: &[char] = &[
27-
'\u{200B}', '\u{200C}', '\u{200D}', '\u{FEFF}', // zero-width
28-
'\u{202A}', '\u{202B}', '\u{202C}', '\u{202D}', '\u{202E}', // bidi
29-
'\u{2028}', '\u{2029}', // line/para separators
30-
'\u{2066}', '\u{2067}', '\u{2068}', '\u{2069}', // directional isolates
31-
];
24+
/// Returns `true` for Unicode characters that are dangerous but not caught by
25+
/// ASCII-range byte checks or `char::is_control()`: zero-width chars, bidi
26+
/// overrides, Unicode line/paragraph separators, and directional isolates.
27+
///
28+
/// Using `matches!` with char ranges gives O(1) per character instead of the
29+
/// O(M) linear scan that a slice `.contains()` would require.
30+
fn is_rejected_unicode(c: char) -> bool {
31+
matches!(c,
32+
// zero-width: ZWSP, ZWNJ, ZWJ, BOM/ZWNBSP
33+
'\u{200B}'..='\u{200D}' | '\u{FEFF}' |
34+
// bidi: LRE, RLE, PDF, LRO, RLO
35+
'\u{202A}'..='\u{202E}' |
36+
// line / paragraph separators
37+
'\u{2028}'..='\u{2029}' |
38+
// directional isolates: LRI, RLI, FSI, PDI
39+
'\u{2066}'..='\u{2069}'
40+
)
41+
}
3242

3343
/// Validates that `dir` is a safe output directory.
3444
///
@@ -136,7 +146,7 @@ fn reject_control_chars(value: &str, flag_name: &str) -> Result<(), GwsError> {
136146
"{flag_name} contains invalid control characters"
137147
)));
138148
}
139-
if value.chars().any(|c| REJECTED_UNICODE_CHARS.contains(&c)) {
149+
if value.chars().any(is_rejected_unicode) {
140150
return Err(GwsError::Validation(format!(
141151
"{flag_name} contains invalid Unicode characters"
142152
)));
@@ -221,7 +231,7 @@ pub fn validate_resource_name(s: &str) -> Result<&str, GwsError> {
221231
"Resource name contains invalid characters: {s}"
222232
)));
223233
}
224-
if s.chars().any(|c| REJECTED_UNICODE_CHARS.contains(&c)) {
234+
if s.chars().any(is_rejected_unicode) {
225235
return Err(GwsError::Validation(format!(
226236
"Resource name contains invalid Unicode characters: {s}"
227237
)));

0 commit comments

Comments
 (0)