use ByteStr;
pub trait Matcher {}
pub trait IntoMatcher {
type Matcher: Matcher;
fn into_matcher(self) -> Self::Matcher;
}
pub trait PrefixMatcher: Matcher {
fn is_prefix_of(&self, haystack: &ByteStr) -> bool;
}
pub trait SufixMatcher: Matcher {
fn is_sufix_of(&self, haystack: &ByteStr) -> bool;
}
pub trait FullMatcher: Matcher {
fn matches(&self, haystack: &ByteStr) -> bool;
}
pub trait ForwardSearcher: Matcher {
fn find(&self, haystack: &ByteStr) -> Option<(usize, usize)>;
}
pub trait ReverseSearcher: Matcher {
fn rfind(&self, haystack: &ByteStr) -> Option<(usize, usize)>;
}
pub trait DoubleEndedSearcher: ForwardSearcher + ReverseSearcher {}
pub struct StrMatcher<'a> {
needle: &'a ByteStr,
}
impl<'a> StrMatcher<'a> {
#[inline]
pub fn new(needle: &'a ByteStr) -> Self {
Self { needle: needle }
}
}
impl<'a> Matcher for StrMatcher<'a> {}
impl<'a, T: AsRef<[u8]>> IntoMatcher for &'a T {
type Matcher = StrMatcher<'a>;
#[inline]
fn into_matcher(self) -> StrMatcher<'a> {
StrMatcher::new(ByteStr::from_slice(self.as_ref()))
}
}
impl<'a> PrefixMatcher for StrMatcher<'a> {
fn is_prefix_of(&self, haystack: &ByteStr) -> bool {
haystack.len() >= self.needle.len() && haystack[0 .. self.needle.len()] == self.needle[..]
}
}
impl<'a> SufixMatcher for StrMatcher<'a> {
fn is_sufix_of(&self, haystack: &ByteStr) -> bool {
haystack.len() >= self.needle.len() &&
haystack[haystack.len() - self.needle.len() .. haystack.len()] == self.needle[..]
}
}
impl<'a> FullMatcher for StrMatcher<'a> {
#[inline]
fn matches(&self, haystack: &ByteStr) -> bool {
haystack == self.needle
}
}
impl<'a> ForwardSearcher for StrMatcher<'a> {
fn find(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
for (i, window) in haystack.windows(self.needle.len()).enumerate() {
if window == self.needle {
return Some((i, i + self.needle.len()));
}
}
None
}
}
impl<'a> ReverseSearcher for StrMatcher<'a> {
fn rfind(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
for (i, window) in haystack.windows(self.needle.len()).enumerate().rev() {
if window == self.needle {
return Some((i, i + self.needle.len()));
}
}
None
}
}
pub struct ByteMatcher {
needle: u8,
}
impl ByteMatcher {
#[inline]
pub fn new(needle: u8) -> Self {
ByteMatcher { needle: needle }
}
}
impl Matcher for ByteMatcher {}
impl IntoMatcher for u8 {
type Matcher = ByteMatcher;
fn into_matcher(self) -> ByteMatcher {
ByteMatcher::new(self)
}
}
impl PrefixMatcher for ByteMatcher {
#[inline]
fn is_prefix_of(&self, haystack: &ByteStr) -> bool {
haystack.first().map_or(false, |&byte| byte == self.needle)
}
}
impl SufixMatcher for ByteMatcher {
#[inline]
fn is_sufix_of(&self, haystack: &ByteStr) -> bool {
haystack.last().map_or(false, |&byte| byte == self.needle)
}
}
impl FullMatcher for ByteMatcher {
#[inline]
fn matches(&self, haystack: &ByteStr) -> bool {
haystack == [self.needle]
}
}
impl ForwardSearcher for ByteMatcher {
fn find(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
for (i, &byte) in haystack.iter().enumerate() {
if byte == self.needle {
return Some((i, i + 1));
}
}
None
}
}
impl ReverseSearcher for ByteMatcher {
fn rfind(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
for (i, &byte) in haystack.iter().enumerate().rev() {
if byte == self.needle {
return Some((i, i + 1));
}
}
None
}
}
impl DoubleEndedSearcher for ByteMatcher {}