syncat-stylesheet 3.6.0

Parser for Syncat Stylesheets.
Documentation
use super::{Selector, Style, Value, helper::*};
use crate::{Matches, Query};
use std::collections::BTreeMap;
use tree_sitter::TreeCursor;

#[derive(Clone, Debug)]
pub(crate) struct Rule {
    pub(crate) selectors: Vec<Selector>,
    pub(crate) styles: Vec<Style>,
}

impl Rule {
    fn matches<'k, 's, 'a: 's>(&'k self, query: &'a Query<'s>) -> Option<Matches<'k, 's>> {
        self.selectors
            .iter()
            .find_map(|selector| selector.matches(query))
    }

    pub(crate) fn styles<'a>(
        &self,
        query: &'a Query<'a>,
        variables: &BTreeMap<String, Value>,
    ) -> Option<crate::Style> {
        let matches = self.matches(query)?;
        let mut style = crate::Style::default();
        for Style { name, value } in &self.styles {
            if let Some(value) = value.resolve(variables, &matches) {
                style.insert(name.as_str(), value);
            }
        }
        Some(style)
    }
}

impl FromSource for Rule {
    fn from_source(tree: &mut TreeCursor, source: &[u8]) -> crate::Result<Self> {
        children!(tree, "rule");
        children!(tree, "selectors");
        let mut selectors = vec![];
        while {
            if !tree.node().is_extra() && tree.node().is_named() {
                selectors.push(Selector::from_source(tree, source)?);
            }
            tree.goto_next_sibling()
        } {}
        tree.goto_parent();
        tree.goto_next_sibling();
        children!(tree, "styles");
        let mut styles = vec![];
        while {
            if tree.node().is_named() && !tree.node().is_extra() {
                styles.push(Style::from_source(tree, source)?);
            }
            tree.goto_next_sibling()
        } {}
        tree.goto_parent();
        tree.goto_parent();
        Ok(Rule { selectors, styles })
    }
}