attr valid: return whether attrs non-empty

This commit is contained in:
Noah Hellman 2023-01-16 17:24:27 +01:00
parent 161dfec96d
commit b512c670e6
3 changed files with 39 additions and 16 deletions

View file

@ -10,13 +10,18 @@ pub(crate) fn parse<'s, S: DiscontinuousString<'s>>(chars: S) -> Attributes<'s>
a
}
pub fn valid<I: Iterator<Item = char>>(chars: I) -> usize {
pub fn valid<I: Iterator<Item = char>>(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));
}
}

View file

@ -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] != "\\")

View file

@ -239,12 +239,12 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
.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<I: Iterator<Item = char> + Clone> Parser<I> {
};
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<I: Iterator<Item = char> + Clone> Parser<I> {
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() {