litcheck_filecheck/pattern/matcher/matchers/
whitespace.rs1use crate::common::*;
2
3#[derive(Debug)]
7pub struct AsciiWhitespaceMatcher {
8 span: SourceSpan,
9}
10impl AsciiWhitespaceMatcher {
11 pub const fn new(span: SourceSpan) -> Self {
12 Self { span }
13 }
14}
15impl MatcherMut for AsciiWhitespaceMatcher {
16 #[inline]
17 fn try_match_mut<'input, 'context, C>(
18 &self,
19 input: Input<'input>,
20 context: &mut C,
21 ) -> DiagResult<MatchResult<'input>>
22 where
23 C: Context<'input, 'context> + ?Sized,
24 {
25 self.try_match(input, context)
26 }
27}
28impl Matcher for AsciiWhitespaceMatcher {
29 #[inline]
30 fn try_match<'input, 'context, C>(
31 &self,
32 input: Input<'input>,
33 context: &C,
34 ) -> DiagResult<MatchResult<'input>>
35 where
36 C: Context<'input, 'context> + ?Sized,
37 {
38 let buffer = input.as_slice();
39 if input.is_empty() || !buffer[0].is_ascii_whitespace() {
40 return Ok(MatchResult::failed(
41 CheckFailedError::MatchNoneButExpected {
42 span: self.span,
43 match_file: context.match_file(),
44 note: None,
45 },
46 ));
47 }
48
49 let start = input.start();
50 let mut len = 0;
51 for c in buffer.iter() {
52 match c {
53 b'\n' => break,
54 c if !c.is_ascii_whitespace() => break,
55 _ => {
56 len += 1;
57 }
58 }
59 }
60
61 Ok(MatchResult::ok(MatchInfo::new(
62 start..(start + len),
63 self.span,
64 )))
65 }
66}
67impl Spanned for AsciiWhitespaceMatcher {
68 #[inline(always)]
69 fn span(&self) -> SourceSpan {
70 self.span
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn test_whitespace_matcher() -> DiagResult<()> {
80 let mut input = String::new();
81 input.push('\t');
82 input.push('\r');
83 input.push(' ');
84 input.push('\n');
85 input.push_str("abc");
86 input.push('\n');
87
88 let mut context = TestContext::new();
89 context.with_checks("").with_input(input.clone());
90
91 let mctx = context.match_context();
92
93 let matcher = AsciiWhitespaceMatcher::new(SourceSpan::from(0..0));
94 let bytes = input.as_bytes();
95 let input = Input::new(bytes, false).span(0..);
96 let result = matcher.try_match(input, &mctx)?;
97 let info = result.info.expect("expected match");
98 assert_eq!(info.span.offset(), 0);
99 assert_eq!(info.span.len(), 3);
100 Ok(())
101 }
102}