1#[cfg(feature = "levenshtein")]
2pub use self::levenshtein::{Levenshtein, LevenshteinError};
3
4#[cfg(feature = "levenshtein")]
5mod levenshtein;
6
7pub trait Automaton {
29 type State;
31
32 fn start(&self) -> Self::State;
37
38 fn is_match(&self, state: &Self::State) -> bool;
40
41 fn can_match(&self, _state: &Self::State) -> bool {
51 true
52 }
53
54 fn will_always_match(&self, _state: &Self::State) -> bool {
65 false
66 }
67
68 fn accept(&self, state: &Self::State, byte: u8) -> Self::State;
70
71 fn accept_eof(&self, _: &Self::State) -> Option<Self::State> {
73 None
74 }
75
76 fn starts_with(self) -> StartsWith<Self>
79 where
80 Self: Sized,
81 {
82 StartsWith(self)
83 }
84
85 fn union<Rhs: Automaton>(self, rhs: Rhs) -> Union<Self, Rhs>
88 where
89 Self: Sized,
90 {
91 Union(self, rhs)
92 }
93
94 fn intersection<Rhs: Automaton>(self, rhs: Rhs) -> Intersection<Self, Rhs>
97 where
98 Self: Sized,
99 {
100 Intersection(self, rhs)
101 }
102
103 fn complement(self) -> Complement<Self>
106 where
107 Self: Sized,
108 {
109 Complement(self)
110 }
111}
112
113impl<'a, T: Automaton> Automaton for &'a T {
114 type State = T::State;
115
116 fn start(&self) -> T::State {
117 (*self).start()
118 }
119
120 fn is_match(&self, state: &T::State) -> bool {
121 (*self).is_match(state)
122 }
123
124 fn can_match(&self, state: &T::State) -> bool {
125 (*self).can_match(state)
126 }
127
128 fn will_always_match(&self, state: &T::State) -> bool {
129 (*self).will_always_match(state)
130 }
131
132 fn accept(&self, state: &T::State, byte: u8) -> T::State {
133 (*self).accept(state, byte)
134 }
135
136 fn accept_eof(&self, state: &Self::State) -> Option<Self::State> {
137 (*self).accept_eof(state)
138 }
139}
140
141#[derive(Clone, Debug)]
169pub struct Str<'a> {
170 string: &'a [u8],
171}
172
173impl<'a> Str<'a> {
174 #[inline]
176 #[must_use]
177 pub fn new(string: &'a str) -> Str<'a> {
178 Str { string: string.as_bytes() }
179 }
180}
181
182impl<'a> Automaton for Str<'a> {
183 type State = Option<usize>;
184
185 #[inline]
186 fn start(&self) -> Option<usize> {
187 Some(0)
188 }
189
190 #[inline]
191 fn is_match(&self, pos: &Option<usize>) -> bool {
192 *pos == Some(self.string.len())
193 }
194
195 #[inline]
196 fn can_match(&self, pos: &Option<usize>) -> bool {
197 pos.is_some()
198 }
199
200 #[inline]
201 fn accept(&self, pos: &Option<usize>, byte: u8) -> Option<usize> {
202 if let Some(pos) = *pos {
204 if self.string.get(pos).copied() == Some(byte) {
206 return Some(pos + 1);
208 }
209 }
210 None
212 }
213}
214
215#[derive(Clone, Debug)]
242pub struct Subsequence<'a> {
243 subseq: &'a [u8],
244}
245
246impl<'a> Subsequence<'a> {
247 #[inline]
250 #[must_use]
251 pub fn new(subsequence: &'a str) -> Subsequence<'a> {
252 Subsequence { subseq: subsequence.as_bytes() }
253 }
254}
255
256impl<'a> Automaton for Subsequence<'a> {
257 type State = usize;
258
259 #[inline]
260 fn start(&self) -> usize {
261 0
262 }
263
264 #[inline]
265 fn is_match(&self, &state: &usize) -> bool {
266 state == self.subseq.len()
267 }
268
269 #[inline]
270 fn can_match(&self, _: &usize) -> bool {
271 true
272 }
273
274 #[inline]
275 fn will_always_match(&self, &state: &usize) -> bool {
276 state == self.subseq.len()
277 }
278
279 #[inline]
280 fn accept(&self, &state: &usize, byte: u8) -> usize {
281 if state == self.subseq.len() {
282 return state;
283 }
284 state + usize::from(byte == self.subseq[state])
285 }
286}
287
288#[derive(Clone, Debug)]
293pub struct AlwaysMatch;
294
295impl Automaton for AlwaysMatch {
296 type State = ();
297
298 #[inline]
299 fn start(&self) {}
300 #[inline]
301 fn is_match(&self, (): &()) -> bool {
302 true
303 }
304 #[inline]
305 fn can_match(&self, (): &()) -> bool {
306 true
307 }
308 #[inline]
309 fn will_always_match(&self, (): &()) -> bool {
310 true
311 }
312 #[inline]
313 fn accept(&self, (): &(), _: u8) {}
314}
315
316#[derive(Clone, Debug)]
319pub struct StartsWith<A>(A);
320
321pub struct StartsWithState<A: Automaton>(StartsWithStateKind<A>);
323
324enum StartsWithStateKind<A: Automaton> {
325 Done,
326 Running(A::State),
327}
328
329impl<A: Automaton> Automaton for StartsWith<A> {
330 type State = StartsWithState<A>;
331
332 fn start(&self) -> StartsWithState<A> {
333 StartsWithState({
334 let inner = self.0.start();
335 if self.0.is_match(&inner) {
336 StartsWithStateKind::Done
337 } else {
338 StartsWithStateKind::Running(inner)
339 }
340 })
341 }
342
343 fn is_match(&self, state: &StartsWithState<A>) -> bool {
344 match state.0 {
345 StartsWithStateKind::Done => true,
346 StartsWithStateKind::Running(_) => false,
347 }
348 }
349
350 fn can_match(&self, state: &StartsWithState<A>) -> bool {
351 match state.0 {
352 StartsWithStateKind::Done => true,
353 StartsWithStateKind::Running(ref inner) => self.0.can_match(inner),
354 }
355 }
356
357 fn will_always_match(&self, state: &StartsWithState<A>) -> bool {
358 match state.0 {
359 StartsWithStateKind::Done => true,
360 StartsWithStateKind::Running(_) => false,
361 }
362 }
363
364 fn accept(
365 &self,
366 state: &StartsWithState<A>,
367 byte: u8,
368 ) -> StartsWithState<A> {
369 StartsWithState(match state.0 {
370 StartsWithStateKind::Done => StartsWithStateKind::Done,
371 StartsWithStateKind::Running(ref inner) => {
372 let next_inner = self.0.accept(inner, byte);
373 if self.0.is_match(&next_inner) {
374 StartsWithStateKind::Done
375 } else {
376 StartsWithStateKind::Running(next_inner)
377 }
378 }
379 })
380 }
381}
382
383#[derive(Clone, Debug)]
385pub struct Union<A, B>(A, B);
386
387pub struct UnionState<A: Automaton, B: Automaton>(A::State, B::State);
389
390impl<A: Automaton, B: Automaton> Automaton for Union<A, B> {
391 type State = UnionState<A, B>;
392
393 fn start(&self) -> UnionState<A, B> {
394 UnionState(self.0.start(), self.1.start())
395 }
396
397 fn is_match(&self, state: &UnionState<A, B>) -> bool {
398 self.0.is_match(&state.0) || self.1.is_match(&state.1)
399 }
400
401 fn can_match(&self, state: &UnionState<A, B>) -> bool {
402 self.0.can_match(&state.0) || self.1.can_match(&state.1)
403 }
404
405 fn will_always_match(&self, state: &UnionState<A, B>) -> bool {
406 self.0.will_always_match(&state.0)
407 || self.1.will_always_match(&state.1)
408 }
409
410 fn accept(&self, state: &UnionState<A, B>, byte: u8) -> UnionState<A, B> {
411 UnionState(
412 self.0.accept(&state.0, byte),
413 self.1.accept(&state.1, byte),
414 )
415 }
416}
417
418#[derive(Clone, Debug)]
420pub struct Intersection<A, B>(A, B);
421
422pub struct IntersectionState<A: Automaton, B: Automaton>(A::State, B::State);
424
425impl<A: Automaton, B: Automaton> Automaton for Intersection<A, B> {
426 type State = IntersectionState<A, B>;
427
428 fn start(&self) -> IntersectionState<A, B> {
429 IntersectionState(self.0.start(), self.1.start())
430 }
431
432 fn is_match(&self, state: &IntersectionState<A, B>) -> bool {
433 self.0.is_match(&state.0) && self.1.is_match(&state.1)
434 }
435
436 fn can_match(&self, state: &IntersectionState<A, B>) -> bool {
437 self.0.can_match(&state.0) && self.1.can_match(&state.1)
438 }
439
440 fn will_always_match(&self, state: &IntersectionState<A, B>) -> bool {
441 self.0.will_always_match(&state.0)
442 && self.1.will_always_match(&state.1)
443 }
444
445 fn accept(
446 &self,
447 state: &IntersectionState<A, B>,
448 byte: u8,
449 ) -> IntersectionState<A, B> {
450 IntersectionState(
451 self.0.accept(&state.0, byte),
452 self.1.accept(&state.1, byte),
453 )
454 }
455}
456
457#[derive(Clone, Debug)]
459pub struct Complement<A>(A);
460
461pub struct ComplementState<A: Automaton>(A::State);
463
464impl<A: Automaton> Automaton for Complement<A> {
465 type State = ComplementState<A>;
466
467 fn start(&self) -> ComplementState<A> {
468 ComplementState(self.0.start())
469 }
470
471 fn is_match(&self, state: &ComplementState<A>) -> bool {
472 !self.0.is_match(&state.0)
473 }
474
475 fn can_match(&self, state: &ComplementState<A>) -> bool {
476 !self.0.will_always_match(&state.0)
477 }
478
479 fn will_always_match(&self, state: &ComplementState<A>) -> bool {
480 !self.0.can_match(&state.0)
481 }
482
483 fn accept(
484 &self,
485 state: &ComplementState<A>,
486 byte: u8,
487 ) -> ComplementState<A> {
488 ComplementState(self.0.accept(&state.0, byte))
489 }
490}