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// }