atom-engine 5.0.2

A component-oriented template engine built on Tera with props, slots, and provide/inject context
Documentation
use crate::parser::expr_parser::Expr;
use indexmap::IndexMap;

#[derive(Debug, Clone, PartialEq)]
pub struct ArgList {
    pub positional: Vec<Expr>,
    pub named: IndexMap<String, Expr>,
}

impl ArgList {
    pub fn new() -> Self {
        ArgList {
            positional: Vec::new(),
            named: IndexMap::new(),
        }
    }

    pub fn required_expr(&self, index: usize) -> Result<&Expr, String> {
        self.positional
            .get(index)
            .ok_or_else(|| format!("Missing required positional argument at index {}", index))
    }

    pub fn optional_expr(&self, index: usize) -> Option<&Expr> {
        self.positional.get(index)
    }

    pub fn required_string(&self, key: &str) -> Result<String, String> {
        self.named
            .get(key)
            .and_then(|e| {
                if let Expr::Str(_, s) = e {
                    Some(s.clone())
                } else {
                    None
                }
            })
            .ok_or_else(|| format!("Missing or invalid required argument '{}'", key))
    }

    pub fn optional_string(&self, key: &str) -> Option<String> {
        self.named.get(key).and_then(|e| {
            if let Expr::Str(_, s) = e {
                Some(s.clone())
            } else {
                None
            }
        })
    }

    pub fn first(&self) -> Option<&Expr> {
        self.positional.first().or(self.named.values().next())
    }
}

impl Default for ArgList {
    fn default() -> Self {
        Self::new()
    }
}