inline: reuse event buffer between blocks
make sure not to allocate a new buffer on each block
This commit is contained in:
		
					parent
					
						
							
								1e5e56c463
							
						
					
				
			
			
				commit
				
					
						9429f90307
					
				
			
		
					 3 changed files with 45 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -94,6 +94,13 @@ impl<I: Iterator<Item = char> + Clone> Parser<I> {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn reset(&mut self, chars: I) {
 | 
			
		||||
        self.lexer = lex::Lexer::new(chars);
 | 
			
		||||
        self.span = Span::new(0, 0);
 | 
			
		||||
        self.openers.clear();
 | 
			
		||||
        debug_assert!(self.events.is_empty());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn eat(&mut self) -> Option<lex::Token> {
 | 
			
		||||
        let tok = self.lexer.next();
 | 
			
		||||
        if let Some(t) = &tok {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										36
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								src/lib.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -604,8 +604,8 @@ pub struct Parser<'s> {
 | 
			
		|||
 | 
			
		||||
    /// Spans to the inlines in the leaf block currently being parsed.
 | 
			
		||||
    inlines: span::InlineSpans<'s>,
 | 
			
		||||
    /// Inline parser, recreated for each new inline.
 | 
			
		||||
    inline_parser: Option<inline::Parser<span::InlineCharsIter<'s>>>,
 | 
			
		||||
    /// Inline parser.
 | 
			
		||||
    inline_parser: inline::Parser<span::InlineCharsIter<'s>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Heading {
 | 
			
		||||
| 
						 | 
				
			
			@ -629,7 +629,11 @@ struct PrePass<'s> {
 | 
			
		|||
 | 
			
		||||
impl<'s> PrePass<'s> {
 | 
			
		||||
    #[must_use]
 | 
			
		||||
    fn new(src: &'s str, mut tree: block::Tree) -> Self {
 | 
			
		||||
    fn new(
 | 
			
		||||
        src: &'s str,
 | 
			
		||||
        mut tree: block::Tree,
 | 
			
		||||
        inline_parser: &mut inline::Parser<span::InlineCharsIter<'s>>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let mut link_definitions = Map::new();
 | 
			
		||||
        let mut headings: Vec<Heading> = Vec::new();
 | 
			
		||||
        let mut used_ids: Set<&str> = Set::new();
 | 
			
		||||
| 
						 | 
				
			
			@ -667,7 +671,8 @@ impl<'s> PrePass<'s> {
 | 
			
		|||
                    inlines.set_spans(tree.take_inlines());
 | 
			
		||||
                    let mut id_auto = String::new();
 | 
			
		||||
                    let mut last_whitespace = true;
 | 
			
		||||
                    inline::Parser::new(inlines.chars()).for_each(|ev| match ev.kind {
 | 
			
		||||
                    inline_parser.reset(inlines.chars());
 | 
			
		||||
                    inline_parser.for_each(|ev| match ev.kind {
 | 
			
		||||
                        inline::EventKind::Str => {
 | 
			
		||||
                            let mut chars = inlines.slice(ev.span).chars().peekable();
 | 
			
		||||
                            while let Some(c) = chars.next() {
 | 
			
		||||
| 
						 | 
				
			
			@ -767,7 +772,8 @@ impl<'s> Parser<'s> {
 | 
			
		|||
    #[must_use]
 | 
			
		||||
    pub fn new(src: &'s str) -> Self {
 | 
			
		||||
        let tree = block::parse(src);
 | 
			
		||||
        let pre_pass = PrePass::new(src, tree.clone());
 | 
			
		||||
        let mut inline_parser = inline::Parser::new(span::InlineChars::empty(src));
 | 
			
		||||
        let pre_pass = PrePass::new(src, tree.clone(), &mut inline_parser);
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            src,
 | 
			
		||||
| 
						 | 
				
			
			@ -780,13 +786,14 @@ impl<'s> Parser<'s> {
 | 
			
		|||
            footnote_index: 0,
 | 
			
		||||
            footnote_active: false,
 | 
			
		||||
            inlines: span::InlineSpans::new(src),
 | 
			
		||||
            inline_parser: None,
 | 
			
		||||
            inline_parser,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn inline(&mut self) -> Option<Event<'s>> {
 | 
			
		||||
        self.inline_parser.as_mut().and_then(|parser| {
 | 
			
		||||
            let mut inline = parser.next();
 | 
			
		||||
        let mut inline = self.inline_parser.next();
 | 
			
		||||
 | 
			
		||||
        inline.as_ref()?;
 | 
			
		||||
 | 
			
		||||
        let mut first_is_attr = false;
 | 
			
		||||
        let mut attributes = inline.as_ref().map_or_else(Attributes::new, |inl| {
 | 
			
		||||
| 
						 | 
				
			
			@ -799,10 +806,12 @@ impl<'s> Parser<'s> {
 | 
			
		|||
        });
 | 
			
		||||
 | 
			
		||||
        if first_is_attr {
 | 
			
		||||
                inline = parser.next();
 | 
			
		||||
            inline = self.inline_parser.next();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            inline.map(|inline| match inline.kind {
 | 
			
		||||
        inline.map(|inline| {
 | 
			
		||||
            let enter = matches!(inline.kind, inline::EventKind::Enter(_));
 | 
			
		||||
            match inline.kind {
 | 
			
		||||
                inline::EventKind::Enter(c) | inline::EventKind::Exit(c) => {
 | 
			
		||||
                    let t = match c {
 | 
			
		||||
                        inline::Container::Span => Container::Span,
 | 
			
		||||
| 
						 | 
				
			
			@ -870,7 +879,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                            Container::Link(url, ty)
 | 
			
		||||
                        }
 | 
			
		||||
                    };
 | 
			
		||||
                    if matches!(inline.kind, inline::EventKind::Enter(_)) {
 | 
			
		||||
                    if enter {
 | 
			
		||||
                        Event::Start(t, attributes)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        Event::End(t)
 | 
			
		||||
| 
						 | 
				
			
			@ -922,7 +931,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                | inline::EventKind::Placeholder => {
 | 
			
		||||
                    panic!("{:?}", inline)
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -954,8 +963,7 @@ impl<'s> Parser<'s> {
 | 
			
		|||
                            }
 | 
			
		||||
                            if enter && !matches!(l, block::Leaf::CodeBlock) {
 | 
			
		||||
                                self.inlines.set_spans(self.tree.take_inlines());
 | 
			
		||||
                                self.inline_parser =
 | 
			
		||||
                                    Some(inline::Parser::new(self.inlines.chars()));
 | 
			
		||||
                                self.inline_parser.reset(self.inlines.chars());
 | 
			
		||||
                            }
 | 
			
		||||
                            match l {
 | 
			
		||||
                                block::Leaf::Paragraph => Container::Paragraph,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,6 +170,12 @@ impl<'s, I: Iterator<Item = Span>> Iterator for InlineChars<'s, I> {
 | 
			
		|||
 | 
			
		||||
pub type InlineCharsIter<'s> = InlineChars<'s, std::iter::Copied<std::slice::Iter<'static, Span>>>;
 | 
			
		||||
 | 
			
		||||
impl<'s> InlineCharsIter<'s> {
 | 
			
		||||
    pub fn empty(src: &'s str) -> Self {
 | 
			
		||||
        InlineChars::new(src, [].iter().copied())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Discontinuous slices of a [`&str`].
 | 
			
		||||
#[derive(Default, Debug)]
 | 
			
		||||
pub struct InlineSpans<'s> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue