summaryrefslogtreecommitdiffstats
path: root/globset/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'globset/src/lib.rs')
-rw-r--r--globset/src/lib.rs51
1 files changed, 48 insertions, 3 deletions
diff --git a/globset/src/lib.rs b/globset/src/lib.rs
index 056118a3..b9a36d3a 100644
--- a/globset/src/lib.rs
+++ b/globset/src/lib.rs
@@ -226,10 +226,21 @@ type Fnv = hash::BuildHasherDefault<fnv::FnvHasher>;
/// single pass.
#[derive(Clone, Debug)]
pub struct GlobSet {
+ len: usize,
strats: Vec<GlobSetMatchStrategy>,
}
impl GlobSet {
+ /// Returns true if this set is empty, and therefore matches nothing.
+ pub fn is_empty(&self) -> bool {
+ self.len == 0
+ }
+
+ /// Returns the number of globs in this set.
+ pub fn len(&self) -> usize {
+ self.len
+ }
+
/// Returns true if any glob in this set matches the path given.
pub fn is_match<P: AsRef<Path>>(&self, path: P) -> bool {
self.is_match_candidate(&Candidate::new(path.as_ref()))
@@ -240,6 +251,9 @@ impl GlobSet {
/// This takes a Candidate as input, which can be used to amortize the
/// cost of preparing a path for matching.
pub fn is_match_candidate(&self, path: &Candidate) -> bool {
+ if self.is_empty() {
+ return false;
+ }
for strat in &self.strats {
if strat.is_match(path) {
return true;
@@ -250,9 +264,6 @@ impl GlobSet {
/// Returns the sequence number of every glob pattern that matches the
/// given path.
- ///
- /// This takes a Candidate as input, which can be used to amortize the
- /// cost of preparing a path for matching.
pub fn matches<P: AsRef<Path>>(&self, path: P) -> Vec<usize> {
self.matches_candidate(&Candidate::new(path.as_ref()))
}
@@ -264,6 +275,9 @@ impl GlobSet {
/// cost of preparing a path for matching.
pub fn matches_candidate(&self, path: &Candidate) -> Vec<usize> {
let mut into = vec![];
+ if self.is_empty() {
+ return into;
+ }
self.matches_candidate_into(path, &mut into);
into
}
@@ -274,12 +288,32 @@ impl GlobSet {
/// `into` is is cleared before matching begins, and contains the set of
/// sequence numbers (in ascending order) after matching ends. If no globs
/// were matched, then `into` will be empty.
+ pub fn matches_into<P: AsRef<Path>>(
+ &self,
+ path: P,
+ into: &mut Vec<usize>,
+ ) {
+ self.matches_candidate_into(&Candidate::new(path.as_ref()), into);
+ }
+
+ /// Adds the sequence number of every glob pattern that matches the given
+ /// path to the vec given.
+ ///
+ /// `into` is is cleared before matching begins, and contains the set of
+ /// sequence numbers (in ascending order) after matching ends. If no globs
+ /// were matched, then `into` will be empty.
+ ///
+ /// This takes a Candidate as input, which can be used to amortize the
+ /// cost of preparing a path for matching.
pub fn matches_candidate_into(
&self,
path: &Candidate,
into: &mut Vec<usize>,
) {
into.clear();
+ if self.is_empty() {
+ return;
+ }
for strat in &self.strats {
strat.matches_into(path, into);
}
@@ -288,6 +322,9 @@ impl GlobSet {
}
fn new(pats: &[Glob]) -> Result<GlobSet, Error> {
+ if pats.is_empty() {
+ return Ok(GlobSet { len: 0, strats: vec![] });
+ }
let mut lits = LiteralStrategy::new();
let mut base_lits = BasenameLiteralStrategy::new();
let mut exts = ExtensionStrategy::new();
@@ -330,6 +367,7 @@ impl GlobSet {
prefixes.literals.len(), suffixes.literals.len(),
required_exts.0.len(), regexes.literals.len());
Ok(GlobSet {
+ len: pats.len(),
strats: vec![
GlobSetMatchStrategy::Extension(exts),
GlobSetMatchStrategy::BasenameLiteral(base_lits),
@@ -750,4 +788,11 @@ mod tests {
assert_eq!(0, matches[0]);
assert_eq!(2, matches[1]);
}
+
+ #[test]
+ fn empty_set_works() {
+ let set = GlobSetBuilder::new().build().unwrap();
+ assert!(!set.is_match(""));
+ assert!(!set.is_match("a"));
+ }
}