use bstr::ByteSlice; use crate::{pattern, pattern::Mode}; #[inline]/// A sloppy parser that performs only the most basic checks, providing additional information/// using `pattern::Mode` flags.////// If `may_alter` is `false`, we won't parse leading `!` or its escaped form.////// Returns `(pattern, mode, no_wildcard_len)`pub fn pattern(mut pat: &[u8], may_alter: bool) -> Option<(&[u8], pattern::Mode, Option<usize>)> { let mut mode = Mode::empty(); if pat.is_empty() { return None; } if may_alter { if pat.first() == Some(&b'!') { mode |= Mode::NEGATIVE; pat = &pat[1..]; } else if pat.first() == Some(&b'\\') { let second = pat.get(1); if second == Some(&b'!') || second == Some(&b'#') { pat = &pat[1..]; } } } if pat.iter().all(u8::is_ascii_whitespace) { return None; } if pat.first() == Some(&b'/') { mode |= Mode::ABSOLUTE; pat = &pat[1..]; } if pat.last() == Some(&b'/') { mode |= Mode::MUST_BE_DIR; pat = &pat[..pat.len() - 1]; } if !pat.contains(&b'/') { mode |= Mode::NO_SUB_DIR; } if pat.first() == Some(&b'*') && first_wildcard_pos(&pat[1..]).is_none() { mode |= Mode::ENDS_WITH; } let pos_of_first_wildcard = first_wildcard_pos(pat); Some((pat, mode, pos_of_first_wildcard))} fn first_wildcard_pos(pat: &[u8]) -> Option<usize> { pat.find_byteset(GLOB_CHARACTERS)} pub(crate) const GLOB_CHARACTERS: &[u8] = br"*?[\";
use bstr::ByteSlice;
use crate::{pattern, pattern::Mode};
#[inline]
/// A sloppy parser that performs only the most basic checks, providing additional information
/// using `pattern::Mode` flags.
///
/// If `may_alter` is `false`, we won't parse leading `!` or its escaped form.
///
/// Returns `(pattern, mode, no_wildcard_len)`
pub fn pattern(mut pat: &[u8], may_alter: bool) -> Option<(&[u8], pattern::Mode, Option<usize>)> {
let mut mode = Mode::empty();
if pat.is_empty() {
return None;
}
if may_alter {
if pat.first() == Some(&b'!') {
mode |= Mode::NEGATIVE;
pat = &pat[1..];
} else if pat.first() == Some(&b'\\') {
let second = pat.get(1);
if second == Some(&b'!') || second == Some(&b'#') {
pat = &pat[1..];
}
}
}
if pat.iter().all(u8::is_ascii_whitespace) {
return None;
}
if pat.first() == Some(&b'/') {
mode |= Mode::ABSOLUTE;
pat = &pat[1..];
}
if pat.last() == Some(&b'/') {
mode |= Mode::MUST_BE_DIR;
pat = &pat[..pat.len() - 1];
}
if !pat.contains(&b'/') {
mode |= Mode::NO_SUB_DIR;
}
if pat.first() == Some(&b'*') && first_wildcard_pos(&pat[1..]).is_none() {
mode |= Mode::ENDS_WITH;
}
let pos_of_first_wildcard = first_wildcard_pos(pat);
Some((pat, mode, pos_of_first_wildcard))
}
fn first_wildcard_pos(pat: &[u8]) -> Option<usize> {
pat.find_byteset(GLOB_CHARACTERS)
}
pub(crate) const GLOB_CHARACTERS: &[u8] = br"*?[\";