quatrain 0.6.0

Not intended to be a static site generator
Documentation
use crate::{Event, Tag};
use std::cell::RefCell;
use std::collections::VecDeque;
use std::ops::Range;

#[derive(Debug, Clone)]
struct Node<'e>(u32, Vec<Event<'e>>);

impl<'e> Node<'e> {
    fn new(level: u32) -> Self {
        Self(level, Vec::with_capacity(1))
    }

    fn push(&mut self, e: Event<'e>) {
        self.1.push(e)
    }
}

#[derive(Debug, Clone)]
struct List<'e>(RefCell<VecDeque<Node<'e>>>);

impl<'e> List<'e> {
    fn new() -> Self {
        List(RefCell::new(VecDeque::new()))
    }

    fn create(&self, level: u32) {
        self.0.borrow_mut().push_back(Node::new(level));
    }

    fn add(&self, event: Event<'e>) {
        // within method should ensure the create been called before the add.
        let index = self.0.borrow().len() - 1;
        self.0.borrow_mut().get_mut(index).unwrap().push(event);
    }
}

#[derive(Debug, Clone)]
pub struct ToC<'e> {
    range: Range<u32>,
    list: List<'e>,
}

impl<'e> ToC<'e> {
    pub fn new(range: Range<u32>) -> Self {
        Self {
            range,
            list: List::new(),
        }
    }

    pub fn start<'f>(&self, event: &Event<'f>) -> bool {
        match &event {
            Event::Start(Tag::Heading(n)) if self.range.contains(&n) => {
                self.list.create(*n);
                true
            }
            _ => false,
        }
    }

    pub fn end<'f>(&self, event: &Event<'f>) -> bool {
        match &event {
            // It should be impossible to construct nesting headings
            // using only Markdown syntax.
            Event::End(Tag::Heading(_)) => true,
            _ => false,
        }
    }

    pub fn within(&self, e: Event<'e>) -> Option<Event<'e>> {
        self.list.add(e.clone());
        Some(e)
    }

    pub fn generate(&self) -> impl Iterator<Item = Event<'e>> {
        let mut v = vec![];
        v.push(Event::Html("<div class=\"sidebar toc\">\n".into()));
        let mut indent = if self.range.start - 1 > 0 {
            self.range.start - 1
        } else {
            0
        };
        for Node(level, ref mut events) in self.list.0.borrow_mut().iter_mut() {
            push_tag(&mut v, indent, *level);
            v.push(Event::Start(Tag::Item));
            v.append(events);
            v.push(Event::End(Tag::Item));
            indent = *level;
        }
        while indent > 0 {
            v.push(Event::End(Tag::List(None)));
            indent -= 1;
        }
        v.push(Event::Html("</div>\n".into()));
        v.into_iter()
    }
}

fn push_tag<'e>(v: &mut Vec<Event<'e>>, indent: u32, level: u32) {
    let mut sub = if level > indent {
        level - indent
    } else {
        indent - level
    };
    while sub > 0 {
        if level > indent {
            v.push(Event::Start(Tag::List(None)));
            sub -= 1;
        } else {
            v.push(Event::End(Tag::List(None)));
            sub -= 1;
        }
    }
}