femstache 0.1.11

Embrace the feminine mustache to unlock your templating dreams! Or something, I don't know. :3
Documentation
use femstache_eval::{BuiltinFunction, EvalError, EvalErrorKind, EvalResult, StringValue, Value};
use femstache_parser::Span;
use femstache_types::{TyId, TyStore};

pub struct Raw;

impl BuiltinFunction for Raw {
    fn types(&self, _store: &TyStore) -> (TyId, TyId) {
        (TyId::STRING, TyId::STRING)
    }

    fn call(&self, value: Value) -> EvalResult<Value> {
        let Some(s) = value.into_string() else {
            // TODO: accurate span
            return Err(EvalError::new(EvalErrorKind::InvalidType, Span::new(0, 0)));
        };
        Ok(Value::String(match s {
            StringValue::Regular(s) => StringValue::Raw(s),
            StringValue::Raw(s) => StringValue::Raw(s),
        }))
    }
}

pub struct ShowInt;

impl BuiltinFunction for ShowInt {
    fn types(&self, _store: &TyStore) -> (TyId, TyId) {
        (TyId::INT, TyId::STRING)
    }

    fn call(&self, value: Value) -> EvalResult<Value> {
        let Some(i) = value.as_int() else {
            // TODO: accurate span
            return Err(EvalError::new(EvalErrorKind::InvalidType, Span::new(0, 0)));
        };
        Ok(Value::string(i.to_string()))
    }
}

pub struct ShowBool;

impl BuiltinFunction for ShowBool {
    fn types(&self, _store: &TyStore) -> (TyId, TyId) {
        (TyId::BOOL, TyId::STRING)
    }

    fn call(&self, value: Value) -> EvalResult<Value> {
        let Some(b) = value.as_bool() else {
            // TODO: accurate span
            return Err(EvalError::new(EvalErrorKind::InvalidType, Span::new(0, 0)));
        };
        Ok(Value::string(b.to_string()))
    }
}

pub fn make_builtins() -> Vec<(String, Value)> {
    let mut builtins = Vec::new();
    builtins.push(("raw".to_owned(), Value::builtin(Raw)));
    builtins.push(("show_int".to_owned(), Value::builtin(ShowInt)));
    builtins.push(("show_bool".to_owned(), Value::builtin(ShowBool)));
    builtins
}