Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement optionally matching on raw bytes #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ categories = ["algorithms"]
repository = "https://github.com/becheran/wildmatch"

[dependencies]
bstr = { version = "1.10", optional = true }
serde = { version = "1.0", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
@@ -22,6 +23,7 @@ regex-lite = {version = "0.1.5"}
rand = {version = "0.8.5"}

[features]
bytes = ["dep:bstr"]
serde = ["dep:serde"]

[[bench]]
68 changes: 65 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -33,7 +33,10 @@
//! assert!(WildMatchPattern::<'%', '_'>::new("%cat%").matches("dog_cat_dog"));
//! ```
use std::fmt;
use std::{fmt, str::Chars};

#[cfg(feature = "bytes")]
use bstr::ByteSlice;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@@ -118,13 +121,25 @@ impl<const MULTI_WILDCARD: char, const SINGLE_WILDCARD: char>
if self.pattern.is_empty() {
return input.is_empty();
}
let mut input_chars = input.chars();
self.matches_inner(input.chars())
}

#[cfg(feature = "bytes")]
/// Returns true if pattern applies to the given input bytes
pub fn matches_bytes(&self, input: &[u8]) -> bool {
if self.pattern.is_empty() {
return input.is_empty();
}
self.matches_inner(input.chars())
}

#[inline]
fn matches_inner<C: CharsWrapper>(&self, mut input_chars: C) -> bool {
let mut pattern_idx = 0;
if let Some(mut input_char) = input_chars.next() {
const NONE: usize = usize::MAX;
let mut start_idx = NONE;
let mut matched = "".chars();
let mut matched = C::new();

loop {
if pattern_idx < self.pattern.len() && self.pattern[pattern_idx] == MULTI_WILDCARD {
@@ -191,6 +206,45 @@ impl<'a, const MULTI_WILDCARD: char, const SINGLE_WILDCARD: char> PartialEq<&'a
}
}

trait CharsWrapper {
fn next(&mut self) -> Option<char>;

fn clone(&self) -> Self;

fn new() -> Self
where
Self: Sized;
}

impl CharsWrapper for Chars<'_> {
fn next(&mut self) -> Option<char> {
std::iter::Iterator::next(self)
}

fn clone(&self) -> Self {
std::clone::Clone::clone(self)
}

fn new() -> Self {
"".chars()
}
}

#[cfg(feature = "bytes")]
impl CharsWrapper for bstr::Chars<'_> {
fn next(&mut self) -> Option<char> {
std::iter::Iterator::next(self)
}

fn clone(&self) -> Self {
std::clone::Clone::clone(self)
}

fn new() -> Self {
b"".chars()
}
}

#[cfg(test)]
mod tests {
use super::*;
@@ -276,6 +330,14 @@ mod tests {
assert!(m.matches(input));
}

#[cfg(feature = "bytes")]
#[test]
fn matches_bytes() {
let m = WildMatch::new("c?t");
assert!(m.matches_bytes(b"c\x00t"));
assert!(m.matches_bytes(b"cat"));
}

#[test_case("*d*")]
#[test_case("*d")]
#[test_case("d*")]

Unchanged files with check annotations Beta

# wildmatch
[![build status](https://github.com/becheran/wildmatch/workflows/Build/badge.svg)](https://github.com/becheran/wildmatch/actions?workflow=Build)
[![docs](https://docs.rs/wildmatch/badge.svg)](https://docs.rs/wildmatch)

Check warning on line 4 in README.md

GitHub Actions / check-links

link checker warning

https://docs.rs/wildmatch. Request was redirected to https://docs.rs/wildmatch/latest/wildmatch/

Check warning on line 4 in README.md

GitHub Actions / check-links

link checker warning

https://docs.rs/wildmatch/badge.svg. Request was redirected to https://img.shields.io/docsrs/wildmatch/latest
[![downloads](https://img.shields.io/crates/v/wildmatch.svg?color=orange)](https://crates.io/crates/wildmatch)
[![crate](https://badgen.net/crates/d/wildmatch)](https://crates.io/crates/wildmatch)
[![license](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Check warning on line 7 in README.md

GitHub Actions / check-links

link checker warning

https://opensource.org/licenses/MIT. Request was redirected to https://opensource.org/license/MIT
[![codecov](https://img.shields.io/codecov/c/github/becheran/wildmatch/master)](https://codecov.io/gh/becheran/wildmatch)

Check warning on line 8 in README.md

GitHub Actions / check-links

link checker warning

https://codecov.io/gh/becheran/wildmatch. Request was redirected to https://app.codecov.io/gh/becheran/wildmatch
Match strings against a simple wildcard pattern. Tests a wildcard pattern `p` against an input string `s`. Returns true only when `p` matches the entirety of `s`.
The library only depends on the rust [`stdlib`](https://doc.rust-lang.org/std/).
See the [documentation](https://docs.rs/wildmatch) for usage and more examples.

Check warning on line 33 in README.md

GitHub Actions / check-links

link checker warning

https://docs.rs/wildmatch. Request was redirected to https://docs.rs/wildmatch/latest/wildmatch/