1use core::marker::PhantomData;
2
3use reborrow_generic::Reborrow;
4
5use crate::back::RbBack;
6use crate::error::ErrorSink;
7use crate::error::std::Unexpected;
8use crate::input::{In, Input};
9use crate::parser::{Parser, ParserMut, ParserOnce, SkipParser, SkipParserMut, SkipParserOnce};
10
11pub trait ExpectedItem<It> {
12 fn eq_item(&self, actual: &It) -> bool;
13}
14
15impl<It: PartialEq> ExpectedItem<It> for It {
16 #[inline]
17 fn eq_item(&self, actual: &It) -> bool {
18 self == actual
19 }
20}
21
22impl<'a, It: PartialEq> ExpectedItem<It> for &'a It {
23 #[inline]
24 fn eq_item(&self, actual: &It) -> bool {
25 *self == actual
26 }
27}
28
29pub trait ItemSeq<It>: Clone {
30 type Item: ExpectedItem<It>;
31 type Iter: Iterator<Item = Self::Item>;
32 fn iter(&self) -> Self::Iter;
33}
34
35impl<'a, It: PartialEq + Clone> ItemSeq<It> for &'a [It] {
36 type Item = &'a It;
37 type Iter = core::slice::Iter<'a, It>;
38 #[inline]
39 fn iter(&self) -> Self::Iter {
40 (*self).iter()
41 }
42}
43
44impl<'a, It: PartialEq + Clone, const N: usize> ItemSeq<It> for &'a [It; N] {
45 type Item = &'a It;
46 type Iter = core::slice::Iter<'a, It>;
47 #[inline]
48 fn iter(&self) -> Self::Iter {
49 self.as_slice().iter()
50 }
51}
52
53impl<'a> ItemSeq<char> for &'a str {
54 type Item = char;
55 type Iter = core::str::Chars<'a>;
56 #[inline]
57 fn iter(&self) -> Self::Iter {
58 self.chars()
59 }
60}
61
62#[inline(always)]
78pub fn tag<S, A>(expected: S) -> Tag<S, A> {
79 Tag(expected, PhantomData)
80}
81
82#[derive(Clone, Copy, Debug, Hash)]
83pub struct Tag<S, A>(pub(crate) S, PhantomData<fn() -> A>);
84
85#[inline]
86fn run_tag<I, N, L, E, S>(mut i: In<I, N, L, E>, expected: S) -> Option<()>
87where
88 I: Input,
89 N: Reborrow,
90 L: RbBack,
91 E: ErrorSink<I::Pos>,
92 S: ItemSeq<I::Item>,
93 Unexpected<I::Item>: Into<E::Error>,
94{
95 for expected in expected.iter() {
96 let p0 = i.input.pos();
97 match i.input.next() {
98 Some(actual) if expected.eq_item(&actual) => {}
99 Some(actual) => {
100 let p1 = i.input.pos();
101 E::push(
102 E::shorten_mut(&mut i.errors),
103 p0..p1,
104 Unexpected::Item(actual).into(),
105 );
106 return None;
107 }
108 None => {
109 let p1 = i.input.pos();
110 E::push(
111 E::shorten_mut(&mut i.errors),
112 p0..p1,
113 Unexpected::EndOfInput.into(),
114 );
115 return None;
116 }
117 }
118 }
119 Some(())
120}
121
122impl<I, N, L, E, S> SkipParserOnce<I, N, L, E> for Tag<S, (I, N, L, E)>
123where
124 I: Input,
125 N: Reborrow,
126 L: RbBack,
127 E: ErrorSink<I::Pos>,
128 S: ItemSeq<I::Item>,
129 Unexpected<I::Item>: Into<E::Error>,
130{
131 #[inline]
132 fn discard_once(self, i: In<I, N, L, E>) -> Option<()> {
133 run_tag(i, self.0)
134 }
135}
136
137impl<I, N, L, E, S> SkipParserMut<I, N, L, E> for Tag<S, (I, N, L, E)>
138where
139 I: Input,
140 N: Reborrow,
141 L: RbBack,
142 E: ErrorSink<I::Pos>,
143 S: ItemSeq<I::Item>,
144 Unexpected<I::Item>: Into<E::Error>,
145{
146 #[inline]
147 fn discard_mut(&mut self, i: In<I, N, L, E>) -> Option<()> {
148 run_tag(i, self.0.clone())
149 }
150}
151
152impl<I, N, L, E, S> SkipParser<I, N, L, E> for Tag<S, (I, N, L, E)>
153where
154 I: Input,
155 N: Reborrow,
156 L: RbBack,
157 E: ErrorSink<I::Pos>,
158 S: ItemSeq<I::Item>,
159 Unexpected<I::Item>: Into<E::Error>,
160{
161 #[inline]
162 fn discard(&self, i: In<I, N, L, E>) -> Option<()> {
163 run_tag(i, self.0.clone())
164 }
165}
166
167impl<I, N, L, E, S> ParserOnce<I, N, L, E> for Tag<S, (I, N, L, E)>
168where
169 I: Input,
170 N: Reborrow,
171 L: RbBack,
172 E: ErrorSink<I::Pos>,
173 S: ItemSeq<I::Item>,
174 Unexpected<I::Item>: Into<E::Error>,
175{
176 type Out = ();
177 #[inline]
178 fn parse_once(self, i: In<I, N, L, E>) -> Option<()> {
179 run_tag(i, self.0)
180 }
181}
182
183impl<I, N, L, E, S> ParserMut<I, N, L, E> for Tag<S, (I, N, L, E)>
184where
185 I: Input,
186 N: Reborrow,
187 L: RbBack,
188 E: ErrorSink<I::Pos>,
189 S: ItemSeq<I::Item>,
190 Unexpected<I::Item>: Into<E::Error>,
191{
192 #[inline]
193 fn parse_mut(&mut self, i: In<I, N, L, E>) -> Option<()> {
194 run_tag(i, self.0.clone())
195 }
196}
197
198impl<I, N, L, E, S> Parser<I, N, L, E> for Tag<S, (I, N, L, E)>
199where
200 I: Input,
201 N: Reborrow,
202 L: RbBack,
203 E: ErrorSink<I::Pos>,
204 S: ItemSeq<I::Item>,
205 Unexpected<I::Item>: Into<E::Error>,
206{
207 #[inline]
208 fn parse(&self, i: In<I, N, L, E>) -> Option<()> {
209 run_tag(i, self.0.clone())
210 }
211}