ct_regex_internal/haystack/hay.rs
1use std::ops::Range;
2
3use crate::haystack::{HaystackItem, HaystackIter, HaystackSlice};
4
5/// A trait used to interface the haystack types use when matching of capturing against a
6/// [`Regex`](crate::expr::Regex), including tracking progression and slicing captures.
7///
8/// It is rare that users will have to interact with this trait, appart from Trait bounds. All
9/// public methods will take an `impl IntoHaystack<'a, H>` as an argument.
10///
11/// `Haystack` is accompanied by another trait, [`HaystackItem`], representing items that can be
12/// matched against a [`Regex`](crate::expr::Regex).
13///
14/// `Haystack`s are stateful and therefore can't be matched against multiple times without being
15/// [`reset`](Self::reset) first, or they will continue where the first pattern finished. They store
16/// their state as a `usize`, which can be obtained via [`index`](Self::index) and restored via
17/// [`rollback`](Self::rollback). Additionally, `Haystack`s are cheap to clone, relying on shallow
18/// clones or reference counting.
19pub trait Haystack<'a>: HaystackIter<'a> {
20 fn is_start(&self) -> bool {
21 self.current_index() == 0
22 }
23
24 fn is_end(&self) -> bool {
25 self.item().is_none()
26 }
27
28 fn item(&self) -> Option<Self::Item> {
29 self.current_item()
30 }
31
32 fn index(&self) -> usize {
33 self.current_index()
34 }
35
36 // Progression is only completed by elements which explicitly check the byte and succeed.
37 fn progress(&mut self) {
38 self.next();
39 }
40
41 fn slice(&self, cap: Range<usize>) -> Self::Slice {
42 self.slice_with(cap)
43 }
44
45 fn reset(&mut self) {
46 self.go_to(0);
47 }
48
49 fn rollback(&mut self, state: usize) -> &mut Self {
50 self.go_to(state);
51 self
52 }
53}
54
55impl<'a, T: HaystackIter<'a>> Haystack<'a> for T {}
56
57/// This trait is exactly the same as [`Haystack`], except that it simplifies bounds by requiring
58/// that `Item = I`.
59///
60/// It is also blanket-implemented for all types that implement `Haystack<Item = I>`.
61pub trait HaystackOf<'a, I: HaystackItem>: Haystack<'a, Slice: HaystackSlice<'a, Item = I>> {}
62
63impl<'a, I, T> HaystackOf<'a, I> for T
64where
65 I: HaystackItem,
66 T: Haystack<'a, Slice: HaystackSlice<'a, Item = I>>
67{}
68
69/// A trait that is responsible for converting a slice into a stateful [`Haystack`], of type `H`.
70/// The primary intent of this trait is to allow users to avoid creating their own `Haystack`,
71/// instead passing a slice to methods on [`Regex`](crate::expr::Regex).
72///
73/// If creating a new `Haystack` type, this trait should be implemented manually so that all types
74/// can be inferred properly.
75pub trait IntoHaystack<'a, H: Haystack<'a>> {
76 /// Creates a new [`Haystack`] from self.
77 fn into_haystack(self) -> H;
78}
79
80// Avoid a blanket implementation here so that users don't have to specify types.
81// impl<'a, I: HaystackItem, H: Haystack<'a, I>> IntoHaystack<'a, I, H> for H::Slice {
82// fn into_haystack(self) -> H {
83// <H as HaystackIter>::from_slice(self)
84// }
85// }