1use core::{fmt::Debug, num::NonZeroUsize};
2use core::ops::{RangeTo, RangeInclusive};
3
4#[derive(Debug)]
6pub enum Never{}
7
8const _: Option<&dyn Pattern<Err = Never>> = None;
10
11#[derive(Clone, Copy, PartialEq, Eq, Debug)]
12pub enum Sep{
15 Retain,
17 Yield,
19 Split,
21 Conjoin,
23}
24
25pub trait Pattern{
31 type Err: Debug;
32 fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err>;
49 fn len(&self) -> NonZeroUsize { NonZeroUsize::new(1).unwrap() }
53 fn sep(&self) -> Sep { Sep::Retain }
57}
58
59impl Pattern for isize {
60 type Err = Never;
61 fn matches(&mut self, _: char, _: &str) -> Result<bool, Self::Err> {
63 *self -= 1;
64 Ok(*self == -1)
65 }
66}
67
68impl Pattern for RangeTo<isize> {
69 type Err = Never;
70 fn matches(&mut self, _: char, _: &str) -> Result<bool, Self::Err> {
71 self.end -= 1;
72 Ok(self.contains(&-1))
73 }
74}
75
76impl Pattern for RangeInclusive<char> {
77 type Err = Never;
78 fn matches(&mut self, c: char, _: &str) -> Result<bool, Self::Err> {
79 Ok(self.contains(&c))
80 }
81}
82
83impl Pattern for char {
84 type Err = Never;
85 fn matches(&mut self, c: char, _: &str) -> Result<bool, Self::Err> {
86 Ok(c == *self)
87 }
88}
89
90impl Pattern for &str {
91 type Err = Never;
92 fn matches(&mut self, _: char, s: &str) -> Result<bool, Self::Err> {
93 Ok(s.starts_with(*self))
94 }
95 fn len(&self) -> NonZeroUsize {
96 NonZeroUsize::new(self.chars().count())
97 .expect("\"\" is not a valid pattern")
98 }
99}
100
101impl Pattern for &[char] {
102 type Err = Never;
103 fn matches(&mut self, c: char, _: &str) -> Result<bool, Self::Err> {
104 Ok(self.contains(&c))
105 }
106}
107
108impl<const N: usize> Pattern for [char; N] {
109 type Err = Never;
110 fn matches(&mut self, c: char, _: &str) -> Result<bool, Self::Err> {
111 Ok(self.contains(&c))
112 }
113}
114
115mod private{
116 pub trait Sealed {}
117}
118
119pub trait FallibleBool: private::Sealed {
121 type Err: Debug;
122 fn get(self) -> Result<bool, Self::Err>;
123}
124
125impl private::Sealed for bool {}
126
127impl FallibleBool for bool {
128 type Err = Never;
129
130 fn get(self) -> Result<bool, Self::Err> {
131 Ok(self)
132 }
133}
134
135impl private::Sealed for Option<bool> {}
136
137impl FallibleBool for Option<bool> {
138 type Err = ();
139
140 fn get(self) -> Result<bool, ()> {
141 self.ok_or(())
142 }
143}
144
145impl<E: Debug> private::Sealed for Result<bool, E> {}
146
147impl<E: Debug> FallibleBool for Result<bool, E> {
148 type Err = E;
149
150 fn get(self) -> Result<bool, E> {
151 self
152 }
153}
154
155impl<F, B> Pattern for F where F: FnMut(char) -> B, B: FallibleBool {
156 type Err = B::Err;
157 fn matches(&mut self, c: char, _: &str) -> Result<bool, Self::Err> {
158 self(c).get()
159 }
160}
161
162pub struct SizedStrPredicate<P: FnMut(&str) -> B, B: FallibleBool> {
163 pattern: P,
164 len: NonZeroUsize
165}
166
167pub trait StrPredicate<B: FallibleBool>: FnMut(&str) -> B + Sized{
170
171 fn expecting(self, len: usize) -> SizedStrPredicate<Self, B> {
183 let len = NonZeroUsize::new(len)
184 .expect("pattern cannot have length 0");
185 SizedStrPredicate { pattern: self, len }
186 }
187}
188
189impl<P: FnMut(&str) -> B, B: FallibleBool> Pattern for SizedStrPredicate<P, B> {
190 type Err = B::Err;
191 fn matches(&mut self, _: char, s: &str) -> Result<bool, Self::Err> {
192 (self.pattern)(s).get()
193 }
194 fn len(&self) -> NonZeroUsize { self.len }
195}
196
197
198pub struct SizedCharStrPredicate<P: FnMut(char, &str) -> B, B: FallibleBool> {
199 pattern: P,
200 len: NonZeroUsize
201}
202
203pub trait CharStrPredicate<B: FallibleBool>: FnMut(char, &str) -> B + Sized{
206
207 fn expecting(self, len: usize) -> SizedCharStrPredicate<Self, B> {
219 let len = NonZeroUsize::new(len)
220 .expect("pattern cannot have length 0");
221 SizedCharStrPredicate { pattern: self, len }
222 }
223}
224
225impl<P: FnMut(char, &str) -> B, B: FallibleBool> Pattern for SizedCharStrPredicate<P, B> {
226 type Err = B::Err;
227
228 fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err> {
229 (self.pattern)(c, s).get()
230 }
231 fn len(&self) -> NonZeroUsize { self.len }
232}
233
234
235pub(crate) struct PatRef<'t, T: Pattern>(pub(crate) &'t mut T);
236
237impl<'t, T: Pattern> Pattern for PatRef<'t, T> {
238 type Err = T::Err;
239 fn len(&self) -> NonZeroUsize {
240 self.0.len()
241 }
242 fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err> {
243 self.0.matches(c, s)
244 }
245 fn sep(&self) -> Sep {
246 self.0.sep()
247 }
248}
249
250#[cfg(feature="std")]
251const _:() = {
252 extern crate alloc;
253 use alloc::boxed::Box;
254
255 impl<E: Debug> Pattern for Box<dyn Pattern<Err = E>> {
256 type Err = E;
257 #[doc(hidden)]
258 fn len(&self) -> NonZeroUsize {
259 self.as_ref().len()
260 }
261 #[doc(hidden)]
262 fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err> {
263 self.as_mut().matches(c, s)
264 }
265 #[doc(hidden)]
266 fn sep(&self) -> Sep {
267 self.as_ref().sep()
268 }
269 }
270};
271
272#[cfg(feature = "std")]
273const _: () = {
274 extern crate alloc;
275
276 use alloc::string::String;
277
278 impl Pattern for String {
279 type Err = Never;
280 fn matches(&mut self, _: char, s: &str) -> Result<bool, Self::Err> {
281 Ok(self == &s)
282 }
283 fn len(&self) -> NonZeroUsize {
284 NonZeroUsize::new(self.chars().count())
285 .expect("\"\" is not a valid pattern")
286 }
287 }
288
289 impl Pattern for &String {
290 type Err = Never;
291 fn matches(&mut self, _: char, s: &str) -> Result<bool, Self::Err> {
292 Ok(self == &s)
293 }
294 fn len(&self) -> NonZeroUsize {
295 NonZeroUsize::new(self.chars().count())
296 .expect("\"\" is not a valid pattern")
297 }
298 }
299};
300
301
302pub struct SepConfig<P: SetSep> {
303 pattern: P,
304 config: Sep,
305}
306
307impl<P: SetSep> Pattern for SepConfig<P> {
308 type Err = P::Err;
309
310 fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err> {
311 self.pattern.matches(c, s)
312 }
313
314 fn len(&self) -> NonZeroUsize { self.pattern.len() }
315
316 fn sep(&self) -> Sep {
317 self.config
318 }
319}
320
321pub trait SetSep: Pattern + Sized {
323
324 fn sep_with(self, sep: Sep) -> SepConfig<Self> {
337 SepConfig {
338 pattern: self,
339 config: sep,
340 }
341 }
342}
343
344impl<P> SetSep for P where P: Pattern + Sized {}
345
346#[macro_export]
348macro_rules! pat {
349 ($p: pat) => {
350 |c: char| matches!(c, $p)
351 };
352 (! $p: pat) => {
353 |c: char| !matches!(c, $p)
354 };
355 ($e: expr => $p: pat ) => {
356 (|s: str| matches!(c, $p)).expecting($e)
357 };
358 ($e: expr => ! $p: pat ) => {
359 (|s: str| !matches!(c, $p)).expecting($e)
360 };
361}