1use std::marker::PhantomData;
14use strcursor::StrCursor;
15use ::ScanError;
16use ::input::ScanInput;
17use ::scanner::{ScanFromStr, ScanStr};
18
19#[cfg(feature="regex")] use regex::Regex;
20
21pub fn exact_width<Then>(width: usize, then: Then) -> ExactWidth<Then> {
29 ExactWidth(width, then)
30}
31
32pub fn exact_width_a<S>(width: usize) -> ExactWidth<ScanA<S>> {
38 exact_width(width, scan_a::<S>())
39}
40
41pub struct ExactWidth<Then>(usize, Then);
47
48impl<'a, Then> ScanStr<'a> for ExactWidth<Then>
49where Then: ScanStr<'a> {
50 type Output = Then::Output;
51
52 fn scan<I: ScanInput<'a>>(&mut self, s: I) -> Result<(Self::Output, usize), ScanError> {
53 let s_str = s.as_str();
54 if s_str.len() < self.0 {
55 return Err(ScanError::syntax("input not long enough"));
56 }
57
58 let sl = s.from_subslice(&s_str[..self.0]);
59
60 match self.1.scan(sl) {
61 Ok((_, n)) if n != self.0 => Err(ScanError::syntax("value did not consume enough characters")),
62 Err(err) => Err(err),
63 Ok((v, _)) => Ok((v, self.0))
64 }
65 }
66
67 fn wants_leading_junk_stripped(&self) -> bool {
68 self.1.wants_leading_junk_stripped()
69 }
70}
71
72#[cfg(test)]
73#[test]
74fn test_exact_width() {
75 use ::ScanError as SE;
76 use ::ScanErrorKind as SEK;
77 use ::scanner::Word;
78 let scan = exact_width_a::<Word>;
79
80 assert_match!(scan(2).scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
81 assert_match!(scan(2).scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
82 assert_match!(scan(2).scan("a b"), Err(SE { kind: SEK::Syntax(_), .. }));
83 assert_match!(scan(2).scan("ab"), Ok(("ab", 2)));
84 assert_match!(scan(2).scan("abc"), Ok(("ab", 2)));
85}
86
87pub fn max_width<Then>(width: usize, then: Then) -> MaxWidth<Then> {
95 MaxWidth(width, then)
96}
97
98pub fn max_width_a<S>(width: usize) -> MaxWidth<ScanA<S>> {
104 max_width(width, scan_a::<S>())
105}
106
107pub struct MaxWidth<Then>(usize, Then);
113
114impl<'a, Then> ScanStr<'a> for MaxWidth<Then>
115where Then: ScanStr<'a> {
116 type Output = Then::Output;
117
118 fn scan<I: ScanInput<'a>>(&mut self, s: I) -> Result<(Self::Output, usize), ScanError> {
119 let s_str = s.as_str();
120 let len = ::std::cmp::min(s_str.len(), self.0);
121 let stop = StrCursor::new_at_left_of_byte_pos(s_str, len);
122 let sl = s.from_subslice(stop.slice_before());
123
124 self.1.scan(sl)
125 }
126
127 fn wants_leading_junk_stripped(&self) -> bool {
128 self.1.wants_leading_junk_stripped()
129 }
130}
131
132#[cfg(test)]
133#[test]
134fn test_max_width() {
135 use ::ScanError as SE;
136 use ::ScanErrorKind as SEK;
137 use ::scanner::Word;
138 let scan = max_width_a::<Word>;
139
140 assert_match!(scan(2).scan(""), Err(SE { kind: SEK::SyntaxNoMessage, .. }));
141 assert_match!(scan(2).scan("a"), Ok(("a", 1)));
142 assert_match!(scan(2).scan("a b"), Ok(("a", 1)));
143 assert_match!(scan(2).scan("ab"), Ok(("ab", 2)));
144 assert_match!(scan(2).scan("abc"), Ok(("ab", 2)));
145}
146
147pub fn min_width<Then>(width: usize, then: Then) -> MinWidth<Then> {
155 MinWidth(width, then)
156}
157
158pub fn min_width_a<S>(width: usize) -> MinWidth<ScanA<S>> {
164 min_width(width, scan_a::<S>())
165}
166
167pub struct MinWidth<Then>(usize, Then);
173
174impl<'a, Then> ScanStr<'a> for MinWidth<Then>
175where Then: ScanStr<'a> {
176 type Output = Then::Output;
177
178 fn scan<I: ScanInput<'a>>(&mut self, s: I) -> Result<(Self::Output, usize), ScanError> {
179 let s_str = s.as_str();
180 if s_str.len() < self.0 {
181 return Err(ScanError::syntax("expected more bytes to scan"));
182 }
183 match self.1.scan(s) {
184 Ok((_, n)) if n < self.0 => Err(ScanError::syntax("scanned value too short")),
185 other => other
186 }
187 }
188
189 fn wants_leading_junk_stripped(&self) -> bool {
190 self.1.wants_leading_junk_stripped()
191 }
192}
193
194#[cfg(test)]
195#[test]
196fn test_min_width() {
197 use ::ScanError as SE;
198 use ::ScanErrorKind as SEK;
199 use ::scanner::Word;
200 let scan = min_width_a::<Word>;
201
202 assert_match!(scan(2).scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
203 assert_match!(scan(2).scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
204 assert_match!(scan(2).scan("a b"), Err(SE { kind: SEK::Syntax(_), .. }));
205 assert_match!(scan(2).scan("ab"), Ok(("ab", 2)));
206 assert_match!(scan(2).scan("abc"), Ok(("abc", 3)));
207}
208
209#[cfg(feature="regex")]
223pub fn re<Then>(s: &str, then: Then) -> ScanRegex<Then> {
224 ScanRegex(Regex::new(s).unwrap(), then)
225}
226
227#[cfg(feature="regex")]
235pub fn re_a<S>(s: &str) -> ScanRegex<ScanA<S>> {
236 re(s, scan_a::<S>())
237}
238
239#[cfg(feature="regex")]
247pub fn re_str(s: &str) -> ScanRegex<ScanA<::scanner::Everything<&str>>> {
248 re_a::<::scanner::Everything<&str>>(s)
249}
250
251#[cfg(feature="regex")]
259pub struct ScanRegex<Then>(Regex, Then);
260
261#[cfg(feature="regex")]
262impl<'a, Then> ScanStr<'a> for ScanRegex<Then>
263where Then: ScanStr<'a> {
264 type Output = Then::Output;
265
266 fn scan<I: ScanInput<'a>>(&mut self, s: I) -> Result<(Self::Output, usize), ScanError> {
267 let s_str = s.as_str();
268 let cap = match self.0.captures(s_str) {
269 None => return Err(ScanError::syntax("no match for regular expression")),
270 Some(cap) => cap,
271 };
272
273 let cover = match cap.pos(0) {
274 None => return Err(ScanError::syntax("no match for regular expression")),
275 Some(pos) => pos,
276 };
277
278 let sl = if let Some(sl) = cap.name("scan") {
279 sl
280 } else if let Some((a, b)) = cap.pos(1) {
281 &s_str[a..b]
282 } else {
283 &s_str[cover.0 .. cover.1]
284 };
285
286 let sl = s.from_subslice(sl);
287
288 match self.1.scan(sl) {
289 Ok((v, _)) => Ok((v, cover.1)),
290 Err(err) => Err(err),
291 }
292 }
293
294 fn wants_leading_junk_stripped(&self) -> bool {
295 self.1.wants_leading_junk_stripped()
296 }
297}
298
299#[cfg(feature="regex")]
300#[cfg(test)]
301#[test]
302fn test_re() {
303 use ::ScanError as SE;
304 use ::ScanErrorKind as SEK;
305 let scan = re_str;
306
307 assert_match!(scan("[a-z][0-9]").scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
308 assert_match!(scan("[a-z][0-9]").scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
309 assert_match!(scan("[a-z][0-9]").scan("a 0"), Err(SE { kind: SEK::Syntax(_), .. }));
310 assert_match!(scan("[a-z][0-9]").scan("a0"), Ok(("a0", 2)));
311 assert_match!(scan("[a-z][0-9]").scan("a0c"), Ok(("a0", 2)));
312 assert_match!(scan("[a-z][0-9]").scan(" a0"), Ok(("a0", 3)));
313}
314
315pub fn scan_a<S>() -> ScanA<S> {
319 ScanA(PhantomData)
320}
321
322pub struct ScanA<S>(PhantomData<S>);
328
329impl<'a, S> ScanStr<'a> for ScanA<S>
330where S: ScanFromStr<'a> {
331 type Output = S::Output;
332
333 fn scan<I: ScanInput<'a>>(&mut self, s: I) -> Result<(Self::Output, usize), ScanError> {
334 <S as ScanFromStr<'a>>::scan_from(s)
335 }
336
337 fn wants_leading_junk_stripped(&self) -> bool {
338 <S as ScanFromStr<'a>>::wants_leading_junk_stripped()
339 }
340}
341
342#[cfg(feature="nightly-pattern")]
352pub fn until_pat<Then, P>(pat: P, then: Then) -> UntilPat<Then, P> {
353 UntilPat(pat, then)
354}
355
356#[cfg(feature="nightly-pattern")]
366pub fn until_pat_a<S, P>(pat: P) -> UntilPat<ScanA<S>, P> {
367 until_pat(pat, scan_a::<S>())
368}
369
370#[cfg(feature="nightly-pattern")]
380pub fn until_pat_str<'a, P>(pat: P) -> UntilPat<ScanA<::scanner::Everything<'a, &'a str>>, P> {
381 until_pat_a::<::scanner::Everything<&str>, _>(pat)
382}
383
384#[cfg(feature="nightly-pattern")]
392pub struct UntilPat<Then, P>(P, Then);
393
394#[cfg(feature="nightly-pattern")]
411impl<'a, Then, P> ScanStr<'a> for UntilPat<Then, P>
412where
413 Then: ScanStr<'a>,
414 for<'b> P: Copy + ::std::str::pattern::Pattern<'b>,
415{
416 type Output = Then::Output;
417
418 fn scan<I: ScanInput<'a>>(&mut self, s: I) -> Result<(Self::Output, usize), ScanError> {
419 let s_str = s.as_str();
420 let off = match s_str.find(self.0) {
421 Some(off) => off,
422 None => return Err(ScanError::syntax("no match for pattern")),
423 };
424
425 let sl = &s_str[..off];
426 let sl = s.from_subslice(sl);
427
428 self.1.scan(sl)
429 }
430
431 fn wants_leading_junk_stripped(&self) -> bool {
432 self.1.wants_leading_junk_stripped()
433 }
434}
435
436#[cfg(feature="nightly-pattern")]
437#[cfg(test)]
438#[test]
439fn test_until() {
440 use ::ScanError as SE;
441 use ::ScanErrorKind as SEK;
442
443 #[allow(non_snake_case)]
444 fn S(s: &str) -> String { String::from(s) }
445
446 assert_match!(until_pat_str("x").scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
447 assert_match!(until_pat_str("x").scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
448 assert_match!(until_pat_str("x").scan("ab"), Err(SE { kind: SEK::Syntax(_), .. }));
449 assert_match!(until_pat_str("x").scan("x"), Ok(("", 0)));
450 assert_match!(until_pat_str("x").scan("ax"), Ok(("a", 1)));
451 assert_match!(until_pat_str("x").scan("abx"), Ok(("ab", 2)));
452
453 assert_match!(until_pat_str(&"x").scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
454 assert_match!(until_pat_str(&"x").scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
455 assert_match!(until_pat_str(&"x").scan("ab"), Err(SE { kind: SEK::Syntax(_), .. }));
456 assert_match!(until_pat_str(&"x").scan("x"), Ok(("", 0)));
457 assert_match!(until_pat_str(&"x").scan("ax"), Ok(("a", 1)));
458 assert_match!(until_pat_str(&"x").scan("abx"), Ok(("ab", 2)));
459
460 assert_match!(until_pat_str(&S("x")).scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
461 assert_match!(until_pat_str(&S("x")).scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
462 assert_match!(until_pat_str(&S("x")).scan("ab"), Err(SE { kind: SEK::Syntax(_), .. }));
463 assert_match!(until_pat_str(&S("x")).scan("x"), Ok(("", 0)));
464 assert_match!(until_pat_str(&S("x")).scan("ax"), Ok(("a", 1)));
465 assert_match!(until_pat_str(&S("x")).scan("abx"), Ok(("ab", 2)));
466
467 assert_match!(until_pat_str('x').scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
468 assert_match!(until_pat_str('x').scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
469 assert_match!(until_pat_str('x').scan("ab"), Err(SE { kind: SEK::Syntax(_), .. }));
470 assert_match!(until_pat_str('x').scan("x"), Ok(("", 0)));
471 assert_match!(until_pat_str('x').scan("ax"), Ok(("a", 1)));
472 assert_match!(until_pat_str('x').scan("abx"), Ok(("ab", 2)));
473
474 assert_match!(until_pat_str(&['x'][..]).scan(""), Err(SE { kind: SEK::Syntax(_), .. }));
475 assert_match!(until_pat_str(&['x'][..]).scan("a"), Err(SE { kind: SEK::Syntax(_), .. }));
476 assert_match!(until_pat_str(&['x'][..]).scan("ab"), Err(SE { kind: SEK::Syntax(_), .. }));
477 assert_match!(until_pat_str(&['x'][..]).scan("x"), Ok(("", 0)));
478 assert_match!(until_pat_str(&['x'][..]).scan("ax"), Ok(("a", 1)));
479 assert_match!(until_pat_str(&['x'][..]).scan("abx"), Ok(("ab", 2)));
480}