pub(super) fn split_top_level_args(args: &str) -> Vec<&str> {
let bytes = args.as_bytes();
let mut parts = Vec::new();
let mut start = 0usize;
let mut depth = 0i32;
let mut in_string: Option<u8> = None;
let mut i = 0;
while i < bytes.len() {
let b = bytes[i];
if let Some(quote) = in_string {
if b == b'\\' && i + 1 < bytes.len() {
i += 2;
continue;
}
if b == quote {
in_string = None;
}
i += 1;
continue;
}
match b {
b'"' | b'\'' => in_string = Some(b),
b'(' | b'[' | b'{' => depth += 1,
b')' | b']' | b'}' => depth -= 1,
b',' if depth == 0 => {
parts.push(&args[start..i]);
start = i + 1;
}
_ => {}
}
i += 1;
}
if !args.is_empty() {
parts.push(&args[start..]);
}
parts
}
pub(super) fn find_matching_close_paren(bytes: &[u8]) -> Option<usize> {
let mut depth: i32 = 0;
let mut in_string: Option<u8> = None;
let mut i = 0;
while i < bytes.len() {
let b = bytes[i];
if let Some(quote) = in_string {
if b == b'\\' && i + 1 < bytes.len() {
i += 2;
continue;
}
if b == quote {
in_string = None;
}
i += 1;
continue;
}
match b {
b'"' | b'\'' => in_string = Some(b),
b'(' | b'[' | b'{' => depth += 1,
b')' | b']' | b'}' => {
if depth == 0 {
return Some(i);
}
depth -= 1;
}
_ => {}
}
i += 1;
}
None
}
pub(super) fn split_top_level_comma(args: &str) -> Option<(&str, &str)> {
let bytes = args.as_bytes();
let mut depth = 0i32;
let mut in_string: Option<u8> = None;
let mut i = 0;
while i < bytes.len() {
let b = bytes[i];
if let Some(quote) = in_string {
if b == b'\\' && i + 1 < bytes.len() {
i += 2;
continue;
}
if b == quote {
in_string = None;
}
i += 1;
continue;
}
match b {
b'"' | b'\'' => in_string = Some(b),
b'(' | b'[' | b'{' => depth += 1,
b')' | b']' | b'}' => depth -= 1,
b',' if depth == 0 => return Some((&args[..i], &args[i + 1..])),
_ => {}
}
i += 1;
}
None
}