1use ByteStr;
9
10pub trait Matcher {}
12
13pub trait IntoMatcher {
15 type Matcher: Matcher;
16
17 fn into_matcher(self) -> Self::Matcher;
18}
19
20pub trait PrefixMatcher: Matcher {
22 fn is_prefix_of(&self, haystack: &ByteStr) -> bool;
23}
24
25pub trait SufixMatcher: Matcher {
27 fn is_sufix_of(&self, haystack: &ByteStr) -> bool;
28}
29
30pub trait FullMatcher: Matcher {
32 fn matches(&self, haystack: &ByteStr) -> bool;
33}
34
35pub trait ForwardSearcher: Matcher {
37 fn find(&self, haystack: &ByteStr) -> Option<(usize, usize)>;
38}
39
40pub trait ReverseSearcher: Matcher {
42 fn rfind(&self, haystack: &ByteStr) -> Option<(usize, usize)>;
43}
44
45pub trait DoubleEndedSearcher: ForwardSearcher + ReverseSearcher {}
47
48pub struct StrMatcher<'a> {
50 needle: &'a ByteStr,
51}
52
53impl<'a> StrMatcher<'a> {
54 #[inline]
55 pub fn new(needle: &'a ByteStr) -> Self {
56 Self { needle: needle }
57 }
58}
59
60impl<'a> Matcher for StrMatcher<'a> {}
61
62impl<'a, T: AsRef<[u8]>> IntoMatcher for &'a T {
63 type Matcher = StrMatcher<'a>;
64
65 #[inline]
66 fn into_matcher(self) -> StrMatcher<'a> {
67 StrMatcher::new(ByteStr::from_slice(self.as_ref()))
68 }
69}
70
71impl<'a> PrefixMatcher for StrMatcher<'a> {
72 fn is_prefix_of(&self, haystack: &ByteStr) -> bool {
73 haystack.len() >= self.needle.len() && haystack[0 .. self.needle.len()] == self.needle[..]
74 }
75}
76
77impl<'a> SufixMatcher for StrMatcher<'a> {
78 fn is_sufix_of(&self, haystack: &ByteStr) -> bool {
79 haystack.len() >= self.needle.len() &&
80 haystack[haystack.len() - self.needle.len() .. haystack.len()] == self.needle[..]
81 }
82}
83
84impl<'a> FullMatcher for StrMatcher<'a> {
85 #[inline]
86 fn matches(&self, haystack: &ByteStr) -> bool {
87 haystack == self.needle
88 }
89}
90
91impl<'a> ForwardSearcher for StrMatcher<'a> {
92 fn find(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
93 for (i, window) in haystack.windows(self.needle.len()).enumerate() {
94 if window == self.needle {
95 return Some((i, i + self.needle.len()));
96 }
97 }
98 None
99 }
100}
101
102impl<'a> ReverseSearcher for StrMatcher<'a> {
103 fn rfind(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
104 for (i, window) in haystack.windows(self.needle.len()).enumerate().rev() {
105 if window == self.needle {
106 return Some((i, i + self.needle.len()));
107 }
108 }
109 None
110 }
111}
112
113pub struct ByteMatcher {
115 needle: u8,
116}
117
118impl ByteMatcher {
119 #[inline]
120 pub fn new(needle: u8) -> Self {
121 ByteMatcher { needle: needle }
122 }
123}
124
125impl Matcher for ByteMatcher {}
126
127impl IntoMatcher for u8 {
128 type Matcher = ByteMatcher;
129
130 fn into_matcher(self) -> ByteMatcher {
131 ByteMatcher::new(self)
132 }
133}
134
135impl PrefixMatcher for ByteMatcher {
136 #[inline]
137 fn is_prefix_of(&self, haystack: &ByteStr) -> bool {
138 haystack.first().map_or(false, |&byte| byte == self.needle)
139 }
140}
141
142impl SufixMatcher for ByteMatcher {
143 #[inline]
144 fn is_sufix_of(&self, haystack: &ByteStr) -> bool {
145 haystack.last().map_or(false, |&byte| byte == self.needle)
146 }
147}
148
149impl FullMatcher for ByteMatcher {
150 #[inline]
151 fn matches(&self, haystack: &ByteStr) -> bool {
152 haystack == [self.needle]
153 }
154}
155
156impl ForwardSearcher for ByteMatcher {
157 fn find(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
158 for (i, &byte) in haystack.iter().enumerate() {
159 if byte == self.needle {
160 return Some((i, i + 1));
161 }
162 }
163 None
164 }
165}
166
167impl ReverseSearcher for ByteMatcher {
168 fn rfind(&self, haystack: &ByteStr) -> Option<(usize, usize)> {
169 for (i, &byte) in haystack.iter().enumerate().rev() {
170 if byte == self.needle {
171 return Some((i, i + 1));
172 }
173 }
174 None
175 }
176}
177
178impl DoubleEndedSearcher for ByteMatcher {}