pub struct Pattern { /* private fields */ }Expand description
A compiled glob pattern.
Implementations§
Source§impl Pattern
impl Pattern
Sourcepub fn has_wildcards(pattern: impl AsRef<[u8]>, options: PatternOptions) -> bool
pub fn has_wildcards(pattern: impl AsRef<[u8]>, options: PatternOptions) -> bool
Reports whether the enabled syntax options make a pattern non-literal.
This is a byte-first preflight helper. Like zlob’s hasWildcards, it
deliberately reports syntax markers even when an escape option would
later make a particular marker literal.
Sourcepub fn compile(
pattern: impl AsRef<[u8]>,
options: PatternOptions,
) -> Result<Self, PatternError>
pub fn compile( pattern: impl AsRef<[u8]>, options: PatternOptions, ) -> Result<Self, PatternError>
Compiles a pattern once for repeated matching against raw path bytes.
use ferralk_glob::{Pattern, PatternOptions};
let source_file = Pattern::compile("src/**/*.{rs,toml}", PatternOptions::walker())?;
assert!(source_file.is_match_glob_path("src/lib.rs"));
assert!(!source_file.is_match_glob_path("src/generated/lib.rs.bak"));§Errors
Returns a PatternError when the pattern is not valid under
options: an unclosed class or extglob group, an invalid range, or a
pattern beyond the compile budget. PatternError::offset locates the
problem in the caller’s pattern bytes.
Sourcepub fn validate(
pattern: impl AsRef<[u8]>,
options: PatternOptions,
) -> Result<(), PatternError>
pub fn validate( pattern: impl AsRef<[u8]>, options: PatternOptions, ) -> Result<(), PatternError>
Reports whether a pattern is syntactically valid without retaining it.
§Errors
Returns the same PatternError that Pattern::compile would.
Sourcepub fn is_match(&self, path: impl AsRef<[u8]>) -> bool
pub fn is_match(&self, path: impl AsRef<[u8]>) -> bool
Matches the entire candidate byte sequence. Ordinary wildcards may
cross separators, and a leading ./ is compared literally.
Use it for text in which / is not special. For a filesystem path,
Self::is_match_glob_path is usually the entry point you want; the
same three candidates are shown on each of the three.
use ferralk_glob::{Pattern, PatternOptions};
let pattern = Pattern::compile("*.rs", PatternOptions::walker())?;
assert!(pattern.is_match("lib.rs"));
// `*` crosses the separator.
assert!(pattern.is_match("src/lib.rs"));
// `./` is compared literally, and `*` does not cover its leading period.
assert!(!pattern.is_match("./lib.rs"));Extglob patterns that fall back to the retained interpreter can still
spend quadratic time on one adversarially long component. For
untrusted path-shaped input, prefer a component-scoped entry point
such as Self::is_match_path where that matches the caller’s
semantics.
Sourcepub fn filter_paths<'a, T>(
&self,
paths: impl IntoIterator<Item = &'a T>,
) -> Vec<&'a T>
pub fn filter_paths<'a, T>( &self, paths: impl IntoIterator<Item = &'a T>, ) -> Vec<&'a T>
Returns the input paths accepted by this compiled pattern, in input
order. Wildcards after an explicit separator stay within that path
component; recursive ** is the separator-crossing form. The returned
references borrow the caller-owned path list.
Each path is asked through Self::is_match_path, zlob’s list rule,
under which a wildcard in the first component crosses separators. For
shell semantics, filter with Self::is_match_glob_path yourself:
use ferralk_glob::{Pattern, PatternOptions};
let paths = ["lib.rs", "src/lib.rs", "src/bin/main.rs", "README.md"];
// A wildcard directly behind `/` stays in its component...
let direct = Pattern::compile("src/*.rs", PatternOptions::walker())?;
assert_eq!(direct.filter_paths(&paths), [&"src/lib.rs"]);
// ...while one in the first component crosses separators.
let top = Pattern::compile("*.rs", PatternOptions::walker())?;
assert_eq!(
top.filter_paths(&paths),
[&"lib.rs", &"src/lib.rs", &"src/bin/main.rs"],
);
// Shell semantics: `*.rs` names the top level only.
let shell: Vec<_> = paths
.iter()
.filter(|path| top.is_match_glob_path(path))
.collect();
assert_eq!(shell, [&"lib.rs"]);Sourcepub fn is_match_path(&self, path: impl AsRef<[u8]>) -> bool
pub fn is_match_path(&self, path: impl AsRef<[u8]>) -> bool
Matches one root-relative path with the zlob list-filter policy used by
Pattern::filter_paths. A root wildcard may cross separators, while
wildcards after an explicit separator are component-local. One leading
./ is ignored on both the pattern and candidate.
use ferralk_glob::{Pattern, PatternOptions};
let pattern = Pattern::compile("*.rs", PatternOptions::walker())?;
assert!(pattern.is_match_path("lib.rs"));
// A wildcard in the first component crosses the separator.
assert!(pattern.is_match_path("src/lib.rs"));
// One leading `./` is ignored.
assert!(pattern.is_match_path("./lib.rs"));
// A wildcard directly behind `/` stays in its component.
let nested = Pattern::compile("src/*.rs", PatternOptions::walker())?;
assert!(!nested.is_match_path("src/bin/main.rs"));Sourcepub fn is_match_glob_path(&self, path: impl AsRef<[u8]>) -> bool
pub fn is_match_glob_path(&self, path: impl AsRef<[u8]>) -> bool
Matches one root-relative filesystem-glob path. Every ordinary
wildcard stays within its path component; recursive ** remains the
separator-crossing form. This is stricter than Pattern::is_match_path
at the root component and is suitable for traversal filters. One
leading ./ is ignored on both the pattern and candidate.
This is how a shell and the ferralk walker read a pattern, and the
entry point to use for a path relative to where the pattern is
anchored. Pass a Path as path_bytes(path).
use ferralk_glob::{Pattern, PatternOptions};
let pattern = Pattern::compile("*.rs", PatternOptions::walker())?;
assert!(pattern.is_match_glob_path("lib.rs"));
// `*` stays in one component; write `**/*.rs` for every depth.
assert!(!pattern.is_match_glob_path("src/lib.rs"));
// One leading `./` is ignored.
assert!(pattern.is_match_glob_path("./lib.rs"));
let recursive = Pattern::compile("**/*.rs", PatternOptions::walker())?;
assert!(recursive.is_match_glob_path("lib.rs"));
assert!(recursive.is_match_glob_path("src/lib.rs"));Sourcepub fn filter_paths_at<'a, T>(
&self,
base_path: impl AsRef<[u8]>,
paths: impl IntoIterator<Item = &'a T>,
) -> Vec<&'a T>
pub fn filter_paths_at<'a, T>( &self, base_path: impl AsRef<[u8]>, paths: impl IntoIterator<Item = &'a T>, ) -> Vec<&'a T>
Returns the input paths accepted relative to base_path, preserving
the original full paths and caller order. Candidates outside the base
directory are ignored.
use ferralk_glob::{Pattern, PatternOptions};
let pattern = Pattern::compile("src/*.rs", PatternOptions::walker())?;
let paths = [
"crates/app/src/lib.rs",
"crates/app/README.md",
"crates/cli/src/main.rs",
"crates/application/src/lib.rs",
];
// Each path is matched below the base and returned in full; a path
// outside it, `crates/application` included, is left out.
assert_eq!(
pattern.filter_paths_at("crates/app", &paths),
[&"crates/app/src/lib.rs"],
);Sourcepub fn filter_path_indices<'a, T>(
&self,
paths: impl IntoIterator<Item = &'a T>,
) -> Vec<usize>
pub fn filter_path_indices<'a, T>( &self, paths: impl IntoIterator<Item = &'a T>, ) -> Vec<usize>
Returns the indices of input paths accepted by this compiled pattern, in their original input order.
Useful when the paths live beside other data, such as a list of records, and the caller wants positions rather than borrowed paths.
use ferralk_glob::{Pattern, PatternOptions};
let pattern = Pattern::compile("src/**/*.rs", PatternOptions::walker())?;
let files = ["README.md", "src/lib.rs", "src/bin/main.rs"].map(String::from);
assert_eq!(pattern.filter_path_indices(&files), [1, 2]);Sourcepub fn filter_path_indices_at<'a, T>(
&self,
base_path: impl AsRef<[u8]>,
paths: impl IntoIterator<Item = &'a T>,
) -> Vec<usize>
pub fn filter_path_indices_at<'a, T>( &self, base_path: impl AsRef<[u8]>, paths: impl IntoIterator<Item = &'a T>, ) -> Vec<usize>
Returns the indices of full input paths accepted relative to
base_path, in their original input order.
use ferralk_glob::{Pattern, PatternOptions};
let pattern = Pattern::compile("*.toml", PatternOptions::walker())?;
let paths = ["crates/app/Cargo.toml", "Cargo.toml", "crates/app/src/x.toml"];
// `Cargo.toml` is outside the base. `src/x.toml` is selected because a
// wildcard in the first component crosses separators under the list
// rule of `filter_paths`.
assert_eq!(pattern.filter_path_indices_at("crates/app", &paths), [0, 2]);Trait Implementations§
Source§impl FromIterator<Pattern> for PatternSet
impl FromIterator<Pattern> for PatternSet
Source§fn from_iter<I: IntoIterator<Item = Pattern>>(patterns: I) -> Self
fn from_iter<I: IntoIterator<Item = Pattern>>(patterns: I) -> Self
Collects compiled patterns into a set, keeping their order and each
member’s own PatternOptions.
use ferralk_glob::{Pattern, PatternOptions, PatternSet};
let set: PatternSet = ["*.rs", "*.toml"]
.iter()
.map(|glob| Pattern::compile(glob, PatternOptions::walker()))
.collect::<Result<_, _>>()?;
assert!(set.is_match_glob_path("Cargo.toml"));