1#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
5pub struct Match {
6 start: usize,
7 end: usize,
8}
9
10impl Match {
11 #[inline]
13 pub fn new(start: usize, end: usize) -> Match {
14 debug_assert!(start <= end);
15 Match { start, end }
16 }
17
18 #[inline]
20 pub fn zero(offset: usize) -> Match {
21 Match {
22 start: offset,
23 end: offset,
24 }
25 }
26
27 #[inline]
29 pub fn start(&self) -> usize {
30 self.start
31 }
32
33 #[inline]
35 pub fn end(&self) -> usize {
36 self.end
37 }
38
39 #[inline]
41 pub fn with_end(&self, end: usize) -> Match {
42 debug_assert!(self.start <= end);
43 Match { end, ..*self }
44 }
45
46 #[inline]
48 pub fn offset(&self, amount: usize) -> Match {
49 Match {
50 start: self.start + amount,
51 end: self.end + amount,
52 }
53 }
54
55 #[inline]
57 pub fn len(&self) -> usize {
58 self.end - self.start
59 }
60
61 #[inline]
63 pub fn is_empty(&self) -> bool {
64 self.len() == 0
65 }
66}
67
68impl std::ops::Index<Match> for [u8] {
69 type Output = [u8];
70
71 #[inline]
72 fn index(&self, index: Match) -> &[u8] {
73 &self[index.start..index.end]
74 }
75}
76
77impl std::ops::IndexMut<Match> for [u8] {
78 #[inline]
79 fn index_mut(&mut self, index: Match) -> &mut [u8] {
80 &mut self[index.start..index.end]
81 }
82}
83
84impl std::ops::Index<Match> for str {
85 type Output = str;
86
87 #[inline]
88 fn index(&self, index: Match) -> &str {
89 &self[index.start..index.end]
90 }
91}
92
93#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
95pub struct LineTerminator(u8);
96
97impl LineTerminator {
98 #[inline]
100 pub fn byte(byte: u8) -> LineTerminator {
101 LineTerminator(byte)
102 }
103
104 #[inline]
106 pub fn as_byte(&self) -> u8 {
107 self.0
108 }
109
110 #[inline]
112 pub fn as_bytes(&self) -> &[u8] {
113 std::slice::from_ref(&self.0)
114 }
115}
116
117impl Default for LineTerminator {
118 #[inline]
119 fn default() -> LineTerminator {
120 LineTerminator(b'\n')
121 }
122}
123
124#[derive(Debug, Eq, PartialEq)]
126pub struct NoError(());
127
128impl std::error::Error for NoError {}
129
130impl std::fmt::Display for NoError {
131 fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 unreachable!("NoError should never be instantiated")
133 }
134}
135
136pub trait Matcher {
138 type Error: std::fmt::Display;
140
141 fn find_at(&self, haystack: &[u8], at: usize) -> Result<Option<Match>, Self::Error>;
143
144 #[inline]
146 fn find(&self, haystack: &[u8]) -> Result<Option<Match>, Self::Error> {
147 self.find_at(haystack, 0)
148 }
149
150 #[inline]
153 fn line_terminator(&self) -> Option<LineTerminator> {
154 None
155 }
156}
157
158impl<M: Matcher> Matcher for &M {
159 type Error = M::Error;
160
161 #[inline]
162 fn find_at(&self, haystack: &[u8], at: usize) -> Result<Option<Match>, Self::Error> {
163 (*self).find_at(haystack, at)
164 }
165
166 #[inline]
167 fn find(&self, haystack: &[u8]) -> Result<Option<Match>, Self::Error> {
168 (*self).find(haystack)
169 }
170
171 #[inline]
172 fn line_terminator(&self) -> Option<LineTerminator> {
173 (*self).line_terminator()
174 }
175}