attr valid: return whether attrs non-empty
This commit is contained in:
		
					parent
					
						
							
								161dfec96d
							
						
					
				
			
			
				commit
				
					
						b512c670e6
					
				
			
		
					 3 changed files with 39 additions and 16 deletions
				
			
		
							
								
								
									
										45
									
								
								src/attr.rs
									
										
									
									
									
								
							
							
						
						
									
										45
									
								
								src/attr.rs
									
										
									
									
									
								
							| 
						 | 
					@ -10,13 +10,18 @@ pub(crate) fn parse<'s, S: DiscontinuousString<'s>>(chars: S) -> Attributes<'s>
 | 
				
			||||||
    a
 | 
					    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);
 | 
					    let mut p = Parser::new(chars);
 | 
				
			||||||
    if p.any(|e| matches!(e, Element::Invalid)) {
 | 
					    for e in &mut p {
 | 
				
			||||||
        0
 | 
					        match e {
 | 
				
			||||||
    } else {
 | 
					            Element::Class(..) | Element::Identifier(..) | Element::Attribute(..) => {
 | 
				
			||||||
        p.pos
 | 
					                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
 | 
					// Attributes are relatively rare, we choose to pay 8 bytes always and sometimes an extra
 | 
				
			||||||
| 
						 | 
					@ -357,7 +362,25 @@ mod test {
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn valid_full() {
 | 
					    fn valid_full() {
 | 
				
			||||||
        let src = "{.class %comment%}";
 | 
					        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]
 | 
					    #[test]
 | 
				
			||||||
| 
						 | 
					@ -365,15 +388,15 @@ mod test {
 | 
				
			||||||
        let src = "{.class}";
 | 
					        let src = "{.class}";
 | 
				
			||||||
        assert_eq!(
 | 
					        assert_eq!(
 | 
				
			||||||
            super::valid(src.chars().chain("{.ignore}".chars())),
 | 
					            super::valid(src.chars().chain("{.ignore}".chars())),
 | 
				
			||||||
            src.len()
 | 
					            (src.len(), true),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn valid_invalid() {
 | 
					    fn valid_invalid() {
 | 
				
			||||||
        assert_eq!(super::valid(" {.valid}".chars()), 0);
 | 
					        assert_eq!(super::valid(" {.valid}".chars()), (0, false));
 | 
				
			||||||
        assert_eq!(super::valid("{.class invalid}".chars()), 0);
 | 
					        assert_eq!(super::valid("{.class invalid}".chars()), (0, false));
 | 
				
			||||||
        assert_eq!(super::valid("abc".chars()), 0);
 | 
					        assert_eq!(super::valid("abc".chars()), (0, false));
 | 
				
			||||||
        assert_eq!(super::valid("{.abc.}".chars()), 0);
 | 
					        assert_eq!(super::valid("{.abc.}".chars()), (0, false));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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()))),
 | 
					                .then(|| (Block::Atom(Attributes), Span::by_len(start, line_t.len()))),
 | 
				
			||||||
            '|' => (&line_t[line_t.len() - 1..] == "|"
 | 
					            '|' => (&line_t[line_t.len() - 1..] == "|"
 | 
				
			||||||
                && &line_t[line_t.len() - 2..line_t.len() - 1] != "\\")
 | 
					                && &line_t[line_t.len() - 2..line_t.len() - 1] != "\\")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,12 +239,12 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
				
			||||||
                .map_or(false, |e| e.kind == EventKind::Str)
 | 
					                .map_or(false, |e| e.kind == EventKind::Str)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            let mut ahead = self.lexer.inner().clone();
 | 
					            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 {
 | 
					            if attr_len > 0 {
 | 
				
			||||||
                while attr_len > 0 {
 | 
					                while attr_len > 0 {
 | 
				
			||||||
                    self.lexer = lex::Lexer::new(ahead.clone());
 | 
					                    self.lexer = lex::Lexer::new(ahead.clone());
 | 
				
			||||||
                    self.span = self.span.extend(attr_len);
 | 
					                    self.span = self.span.extend(attr_len);
 | 
				
			||||||
                    attr_len = attr::valid(&mut ahead);
 | 
					                    attr_len = attr::valid(&mut ahead).0;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let i = self
 | 
					                let i = self
 | 
				
			||||||
| 
						 | 
					@ -345,7 +345,7 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        self.openers.drain(o..);
 | 
					                        self.openers.drain(o..);
 | 
				
			||||||
                        let mut ahead = self.lexer.inner().clone();
 | 
					                        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 {
 | 
					                        if attr_len > 0 {
 | 
				
			||||||
                            let span_closer = self.span;
 | 
					                            let span_closer = self.span;
 | 
				
			||||||
                            self.events[e_attr].span = Span::empty_at(self.span.end());
 | 
					                            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.lexer = lex::Lexer::new(ahead.clone());
 | 
				
			||||||
                                self.span = self.events[e_attr].span.extend(attr_len);
 | 
					                                self.span = self.events[e_attr].span.extend(attr_len);
 | 
				
			||||||
                                self.events[e_attr].span = self.span;
 | 
					                                self.events[e_attr].span = self.span;
 | 
				
			||||||
                                attr_len = attr::valid(&mut ahead);
 | 
					                                attr_len = attr::valid(&mut ahead).0;
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            if event.is_none() {
 | 
					                            if event.is_none() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue