#[must_use]
pub(crate) fn tokenize(query: &str) -> Vec<String> {
let stripped = query.trim();
if stripped.is_empty() {
return Vec::new();
}
match shlex::split(stripped) {
Some(tokens) => tokens.into_iter().filter(|t| !t.is_empty()).collect(),
None => stripped.split_whitespace().map(str::to_owned).collect(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn quoted_phrases_stay_together() {
assert_eq!(tokenize(r#""john doe" admin"#), vec!["john doe", "admin"]);
}
#[test]
fn whitespace_collapses() {
assert_eq!(tokenize(" hello world "), vec!["hello", "world"]);
}
#[test]
fn empty_query_has_no_tokens() {
assert!(tokenize(" ").is_empty());
}
#[test]
fn unbalanced_quotes_fall_back_to_whitespace() {
assert_eq!(tokenize(r#"foo "bar"#), vec!["foo", r#""bar"#]);
}
}