From b512c670e62fb60148b40688731dc33c9796da3c Mon Sep 17 00:00:00 2001 From: Noah Hellman Date: Mon, 16 Jan 2023 17:24:27 +0100 Subject: [PATCH] attr valid: return whether attrs non-empty --- src/attr.rs | 45 ++++++++++++++++++++++++++++++++++----------- src/block.rs | 2 +- src/inline.rs | 8 ++++---- 3 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 1499427..41033a1 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -10,13 +10,18 @@ pub(crate) fn parse<'s, S: DiscontinuousString<'s>>(chars: S) -> Attributes<'s> a } -pub fn valid>(chars: I) -> usize { +pub fn valid>(chars: I) -> (usize, bool) { + let mut has_attr = false; let mut p = Parser::new(chars); - if p.any(|e| matches!(e, Element::Invalid)) { - 0 - } else { - p.pos + for e in &mut p { + match e { + Element::Class(..) | Element::Identifier(..) | Element::Attribute(..) => { + has_attr = true + } + Element::Invalid => return (0, false), + } } + (p.pos, has_attr) } // Attributes are relatively rare, we choose to pay 8 bytes always and sometimes an extra @@ -357,7 +362,25 @@ mod test { #[test] fn valid_full() { let src = "{.class %comment%}"; - assert_eq!(super::valid(src.chars()), src.len()); + assert_eq!(super::valid(src.chars()), (src.len(), true)); + } + + #[test] + fn valid_empty() { + let src = "{}"; + assert_eq!(super::valid(src.chars()), (src.len(), false)); + } + + #[test] + fn valid_whitespace() { + let src = "{ \n }"; + assert_eq!(super::valid(src.chars()), (src.len(), false)); + } + + #[test] + fn valid_comment() { + let src = "{%comment%}"; + assert_eq!(super::valid(src.chars()), (src.len(), false)); } #[test] @@ -365,15 +388,15 @@ mod test { let src = "{.class}"; assert_eq!( super::valid(src.chars().chain("{.ignore}".chars())), - src.len() + (src.len(), true), ); } #[test] fn valid_invalid() { - assert_eq!(super::valid(" {.valid}".chars()), 0); - assert_eq!(super::valid("{.class invalid}".chars()), 0); - assert_eq!(super::valid("abc".chars()), 0); - assert_eq!(super::valid("{.abc.}".chars()), 0); + assert_eq!(super::valid(" {.valid}".chars()), (0, false)); + assert_eq!(super::valid("{.class invalid}".chars()), (0, false)); + assert_eq!(super::valid("abc".chars()), (0, false)); + assert_eq!(super::valid("{.abc.}".chars()), (0, false)); } } diff --git a/src/block.rs b/src/block.rs index f57041d..ffa0a95 100644 --- a/src/block.rs +++ b/src/block.rs @@ -270,7 +270,7 @@ impl BlockParser { )) } } - '{' => (attr::valid(line_t.chars()) == line_t.trim_end().len()) + '{' => (attr::valid(line_t.chars()).0 == line_t.trim_end().len()) .then(|| (Block::Atom(Attributes), Span::by_len(start, line_t.len()))), '|' => (&line_t[line_t.len() - 1..] == "|" && &line_t[line_t.len() - 2..line_t.len() - 1] != "\\") diff --git a/src/inline.rs b/src/inline.rs index ee7056b..9bfa87b 100644 --- a/src/inline.rs +++ b/src/inline.rs @@ -239,12 +239,12 @@ impl + Clone> Parser { .map_or(false, |e| e.kind == EventKind::Str) { let mut ahead = self.lexer.inner().clone(); - let mut attr_len = attr::valid(std::iter::once('{').chain(&mut ahead)) - 1; + let mut attr_len = attr::valid(std::iter::once('{').chain(&mut ahead)).0 - 1; if attr_len > 0 { while attr_len > 0 { self.lexer = lex::Lexer::new(ahead.clone()); self.span = self.span.extend(attr_len); - attr_len = attr::valid(&mut ahead); + attr_len = attr::valid(&mut ahead).0; } let i = self @@ -345,7 +345,7 @@ impl + Clone> Parser { }; self.openers.drain(o..); let mut ahead = self.lexer.inner().clone(); - let mut attr_len = attr::valid(&mut ahead); + let mut attr_len = attr::valid(&mut ahead).0; if attr_len > 0 { let span_closer = self.span; self.events[e_attr].span = Span::empty_at(self.span.end()); @@ -354,7 +354,7 @@ impl + Clone> Parser { self.lexer = lex::Lexer::new(ahead.clone()); self.span = self.events[e_attr].span.extend(attr_len); self.events[e_attr].span = self.span; - attr_len = attr::valid(&mut ahead); + attr_len = attr::valid(&mut ahead).0; } if event.is_none() {