syncat-stylesheet 3.6.0

Parser for Syncat Stylesheets.
Documentation
use crate::resolver::Resolver;
use std::path::Path;
use std::str::FromStr;
use tree_sitter::TreeCursor;

use super::{Declaration, Import, Rule, helper::*};

#[derive(Clone, Debug, Default)]
pub struct Stylesheet {
    pub(crate) imports: Vec<Import>,
    pub(crate) variables: Vec<Declaration>,
    pub(crate) rules: Vec<Rule>,
}

impl Stylesheet {
    pub(crate) fn load<R: Resolver>(path: impl AsRef<Path>, resolver: &R) -> crate::Result<Self> {
        let source = resolver
            .read_to_string(path.as_ref())
            .map_err(|e| crate::Error::missing_module(e, path.as_ref()))?;
        Self::from_str(&source)
    }
}

impl FromStr for Stylesheet {
    type Err = crate::Error;

    fn from_str(source: &str) -> Result<Self, Self::Err> {
        let tree = crate::parser::parse(source).unwrap();
        let mut cursor = tree.walk();
        Self::from_source(&mut cursor, source.as_ref())
    }
}

impl FromSource for Stylesheet {
    fn from_source(tree: &mut TreeCursor, source: &[u8]) -> crate::Result<Self> {
        let mut stylesheet = Self::default();
        if !children!(tree, "stylesheet") {
            return Ok(stylesheet);
        }
        while {
            if !tree.node().is_extra() {
                match tree.node().kind() {
                    "import" => stylesheet.imports.push(Import::from_source(tree, source)?),
                    "declaration" => stylesheet
                        .variables
                        .push(Declaration::from_source(tree, source)?),
                    "rule" => stylesheet.rules.push(Rule::from_source(tree, source)?),
                    name => return Err(crate::Error::invalid("stylesheet_item", name)),
                }
            }
            tree.goto_next_sibling()
        } {}
        tree.goto_parent();
        Ok(stylesheet)
    }
}