mini_template 0.1.1

Small template engine with smarty like syntax
Documentation
use std::collections::HashMap;

use mini_template::{value::Value, MiniTemplate};

#[macro_use]
extern crate mini_template;

const TEMPLATE: &str = include_str!("./custom_modifier.tpl");

fn main() {
    let mut mini_template = MiniTemplate::default();

    mini_template.add_modifier("is_even", &modifiers::is_even);
    mini_template.add_modifier("leading_zeros", &modifiers::leading_zeros);
    mini_template.add_modifier("as_usize", &modifiers::parse_as_usize);
    mini_template.add_modifier("nth_upper", &modifiers::nth_upper);
    mini_template.add_modifier("nth_lower", &modifiers::nth_lower);

    mini_template.add_template(0, TEMPLATE.to_owned()).unwrap();
    let render = mini_template.render(
        &0,
        HashMap::from_iter([
            (String::from("even"), Value::Number(4.)),
            (String::from("zeros"), Value::Number(4.)),
        ]),
    );

    println!("{}", render.unwrap())
}

mod modifiers {

    #[mini_template::macros::create_modifier(mini_template_crate = "mini_template")]
    fn is_even(num: usize) -> bool {
        num % 2 == 0
    }

    mini_template::fn_as_modifier!(
        fn leading_zeros(input: usize) -> u32 => usize::leading_zeros
    );

    #[mini_template::macros::create_modifier(mini_template_crate = "mini_template", returns_result = true)]
    fn parse_as_usize(input: String) -> Result<usize, String> {
        match input.parse::<usize>() {
            Ok(o) => Ok(o),
            Err(_) => Err(format!("Can not parse \"{input}\" as usize")),
        }
    }

    #[mini_template::macros::create_modifier(mini_template_crate = "mini_template", defaults::n = 2)]
    fn nth_upper(input: String, n: usize) -> String {
        let mut buf = String::new();
        for (i, c) in input.chars().enumerate() {
            if i % n == 0 {
                buf.push(c.to_ascii_uppercase())
            } else {
                buf.push(c)
            }
        }
        buf
    }

    pub fn nth_lower(
        input: &mini_template::value::Value,
        args: Vec<&mini_template::value::Value>,
    ) -> mini_template::modifier::Result<mini_template::value::Value> {
        let input: String = match input.try_into() {
            Ok(inner) => inner,
            Err(e) => {
                return Err(mini_template::modifier::Error::Type {
                    value: input.to_string(),
                    type_error: e,
                })
            }
        };

        let n: usize = match (*args
            .get(0)
            .unwrap_or(&&mini_template::value::Value::Number(2.)))
        .try_into()
        {
            Ok(inner) => inner,
            Err(e) => {
                return Err(mini_template::modifier::Error::Type {
                    value: input.to_string(),
                    type_error: e,
                })
            }
        };

        let mut buf = String::new();
        for (i, c) in input.chars().enumerate() {
            if i % n == 0 {
                buf.push(c.to_ascii_lowercase())
            } else {
                buf.push(c)
            }
        }
        Ok(mini_template::value::Value::String(buf))
    }
}