combinedfun/
traits.rs

1use std::ops::{Bound, RangeBounds};
2
3/// The kind of error that can happen with `Parser::or`(crate::Parser::or).
4pub trait AltError<I> {
5    fn alt(self, other: Self, at: I) -> Self;
6}
7
8impl<I> AltError<I> for () {
9    fn alt(self, _: (), _: I) { }
10}
11
12/// Implemented for types that can be tags of the input `I`.
13pub trait Tag<I> {
14    type Output;
15
16    /// The return type is reversed, since the tag is the beginning of the input.
17    fn parse_tag(&self, inp: I) -> Option<(Self::Output, I)>;
18}
19
20impl<'a> Tag<&'a str> for str {
21    type Output = &'a str;
22
23    fn parse_tag(&self, inp: &'a str) -> Option<(&'a str, &'a str)> {
24        if inp.starts_with(self) {
25            Some(inp.split_at(self.len()))
26        } else {
27            None
28        }
29    }
30}
31
32impl<'a, T> Tag<&'a [T]> for [T] where T: PartialEq {
33    type Output = &'a [T];
34
35    fn parse_tag(&self, inp: &'a [T]) -> Option<(&'a [T], &'a [T])> {
36        if inp.starts_with(self) {
37            Some(inp.split_at(self.len()))
38        } else {
39            None
40        }
41    }
42}
43
44impl<'a> Tag<&'a [u8]> for str {
45    type Output = &'a [u8];
46
47    fn parse_tag(&self, inp: &'a [u8]) -> Option<(&'a [u8], &'a [u8])> {
48        self.as_bytes().parse_tag(inp)
49    }
50}
51
52/// The kind of error that can happen with `tag`(crate::tag).
53pub trait TagError<'a, T: ?Sized, I> {
54    fn tag(tag: &'a T, at: I) -> Self;
55}
56
57impl<'a, I, T: ?Sized> TagError<'a, T, I> for () {
58    fn tag(_: &'a T, _: I) { }
59}
60
61/// This trait is implemented for all types that implement [`RangeBounds`](RangeBounds).
62///
63/// In most circumstances, you shouldn't implement it yourself, although there are certainly
64/// applications.
65pub trait RangeLike {
66    fn can_continue(&self, n: usize) -> bool;
67    fn has_to_continue(&self, n: usize) -> bool;
68
69    /// The capacity the container should start with
70    fn capacity(&self) -> usize {
71        0
72    }
73}
74
75fn continue_from_bound(n: usize, bound: Bound<&usize>, unbounded: bool) -> bool {
76    match bound {
77        Bound::Included(&stop) => n < stop,
78        Bound::Excluded(&stop) => n + 1 < stop,
79        Bound::Unbounded => unbounded,
80    }
81}
82
83impl<T> RangeLike for T where T: RangeBounds<usize> {
84    fn can_continue(&self, n: usize) -> bool {
85        continue_from_bound(n, self.end_bound(), true)
86    }
87
88    fn has_to_continue(&self, n: usize) -> bool {
89        continue_from_bound(n, self.start_bound(), false)
90    }
91
92    fn capacity(&self) -> usize {
93        match self.end_bound() {
94            Bound::Included(&n) => n,
95            Bound::Excluded(&n) => n.saturating_sub(1),
96            Bound::Unbounded => match self.start_bound() {
97                Bound::Included(&n) => n,
98                Bound::Excluded(&n) => n + 1,
99                Bound::Unbounded => 0,
100            }
101        }
102    }
103}
104
105/// This trait is implemented for collections you can push to.
106pub trait Collection {
107    type Item;
108
109    fn reserve(&mut self, additional: usize);
110    fn push(&mut self, index: usize, item: Self::Item);
111}
112
113impl<T> Collection for Vec<T> {
114    type Item = T;
115
116    fn reserve(&mut self, additional: usize) {
117        self.reserve(additional);
118    }
119
120    fn push(&mut self, _: usize, item: Self::Item) {
121        self.push(item);
122    }
123}
124
125impl Collection for String {
126    type Item = char;
127
128    fn reserve(&mut self, additional: usize) {
129        self.reserve(additional);
130    }
131
132    fn push(&mut self, _: usize, item: Self::Item) {
133        self.push(item);
134    }
135}
136
137impl<T> Collection for Option<T> {
138    type Item = T;
139
140    fn reserve(&mut self, additional: usize) {
141        assert!(additional <= 1);
142    }
143
144    fn push(&mut self, _: usize, item: Self::Item) {
145        *self = Some(item);
146    }
147}
148
149macro_rules! collection_impl {
150    ($($n:literal)*) => {
151        $(
152            impl<T> Collection for [T;$n] where T: Default {
153                type Item = T;
154
155                fn reserve(&mut self, additional: usize) {
156                    assert!(additional <= $n);
157                }
158
159                fn push(&mut self, index: usize, item: Self::Item) {
160                    self[index] = item;
161                }
162            }
163        )*
164    };
165}
166
167collection_impl!(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32);
168
169/// This trait allows checking if an input has reached its end.
170pub trait HasEof {
171    fn at_eof(&self) -> bool;
172}
173
174impl<'a> HasEof for &'a str {
175    fn at_eof(&self) -> bool {
176        self.is_empty()
177    }
178}
179
180impl<'a, T> HasEof for &'a [T] {
181    fn at_eof(&self) -> bool {
182        self.is_empty()
183    }
184}
185
186/// The kind of error that can happen with `eof`(crate::eof).
187pub trait EofError<I> {
188    fn no_eof(at: I) -> Self;
189}
190
191impl<I> EofError<I> for () {
192    fn no_eof(_: I) { }
193}
194
195/// The kind of error that can happen with `not`(crate::not).
196pub trait NotError<O, I> {
197    fn not(out: O, at: I) -> Self;
198}
199
200impl<O, I> NotError<O, I> for () {
201    fn not(_: O, _: I) { }
202}
203
204/// This trait allows recording what part of an input was consumed by a parser.
205pub trait Recordable {
206    type Output;
207
208    fn record(self, later: Self) -> Self::Output;
209}
210
211impl<'a> Recordable for &'a str {
212    type Output = &'a str;
213
214    fn record(self, later: &'a str) -> &'a str {
215        &self[..(self.len() - later.len())]
216    }
217}
218
219impl<'a, T> Recordable for &'a [T] {
220    type Output = &'a [T];
221
222    fn record(self, later: &'a [T]) -> &'a [T] {
223        &self[..(self.len() - later.len())]
224    }
225}
226
227/// This trait allows removing the first element from the input.
228pub trait SplitFirst: Sized {
229    type Element;
230
231    fn split_first(self) -> Option<(Self::Element, Self)>;
232}
233
234impl<'a> SplitFirst for &'a str {
235    type Element = char;
236
237    fn split_first(self) -> Option<(char, &'a str)> {
238        self.chars().next().map(|c| (c, &self[c.len_utf8()..]))
239    }
240}
241
242impl<'a, T> SplitFirst for &'a [T] {
243    type Element = &'a T;
244
245    fn split_first(self) -> Option<(&'a T, &'a [T])> {
246        self.iter().next().map(|x| (x, &self[1..]))
247    }
248}
249
250/// The kind of error that can happen with `Parser::record_while`(crate::record_while).
251pub trait ConsumeError<I: SplitFirst> {
252    fn eof(at: I) -> Self;
253    fn condition_failed(element: I::Element, at: I) -> Self;
254}
255
256impl<I: SplitFirst> ConsumeError<I> for () {
257    fn eof(_: I) { }
258    fn condition_failed(_: I::Element, _: I) { }
259}
260
261/// Used to track positions in a [`Span`](crate::types::Span).
262pub trait Position<I>: Default {
263    fn record_difference(&self, old: &I, new: &I) -> Self;
264}