mustache2 1.0.5

Logic-less templates.
Documentation
#[cfg(all(feature = "serde", not(feature = "ext-lambdas")))]
use serde::Serialize;
use std::{
    collections::HashMap,
    fmt::{Debug, Display},
};

#[cfg(feature = "ext-lambdas")]
mod lambdas;
#[cfg(feature = "serde")]
mod serialize;

#[cfg(feature = "ext-lambdas")]
pub use lambdas::{Provider, Transformer};
#[cfg(feature = "serde")]
pub use serialize::to_data;

/// Data represents all the possible values that can be fed to a Mustache template
/// during compile time.
#[cfg_attr(
    all(feature = "serde", not(feature = "ext-lambdas")),
    derive(Serialize),
    serde(untagged)
)]
#[derive(Clone)]
pub enum Data {
    /// The JSON null value.
    Null,
    /// A string value.
    String(String),
    /// A boolean value.
    Bool(bool),
    /// An integer value.
    Int(i64),
    /// A floating point value.
    Float(f64),
    /// A vector of multiple values.
    List(Vec<Data>),
    /// A hash map or dictionary of values.
    Map(HashMap<String, Data>),
    #[cfg(feature = "ext-lambdas")]
    /// A lambda function that does not expect any arguments.
    Provider(Provider),
    #[cfg(feature = "ext-lambdas")]
    /// A lambda function that expects a single argument.
    Transformer(Transformer),
}

impl Data {
    /// Returns true if the value is considered "truthy".
    pub fn is_truthy(&self) -> bool {
        match self {
            Data::Null => false,
            Data::String(s) => !s.is_empty(),
            Data::Bool(b) => *b,
            Data::Int(i) => *i != 0,
            Data::Float(fl) => *fl != 0.0,
            Data::List(list) => !list.is_empty(),
            Data::Map(map) => !map.is_empty(),
            #[cfg(feature = "ext-lambdas")]
            Data::Provider(_) | Data::Transformer(_) => true,
        }
    }

    /// This method is a shorthand for `Data::Map(HashMap::from(value))`.
    pub fn map_from<T>(value: T) -> Self
    where
        HashMap<String, Data>: From<T>,
    {
        Self::Map(HashMap::from(value))
    }
}

impl Display for Data {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Data::Null => Ok(()),
            Data::String(str) => f.write_str(str),
            _ => Debug::fmt(self, f),
        }
    }
}

impl Debug for Data {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Data::Null => f.write_str("null"),
            Data::String(str) => write!(f, "\"{str}\""),
            Data::Bool(b) => write!(f, "{b}"),
            Data::Int(i) => write!(f, "{i}"),
            Data::Float(fl) => write!(f, "{fl}"),
            Data::List(data) => {
                let mut list = f.debug_list();
                list.entries(data.iter());
                list.finish()
            }
            Data::Map(data) => {
                let mut map = f.debug_map();
                map.entries(data.iter());
                map.finish()
            }
            #[cfg(feature = "ext-lambdas")]
            Data::Transformer(l) => write!(f, "{l}"),
            #[cfg(feature = "ext-lambdas")]
            Data::Provider(l) => write!(f, "{l}"),
        }
    }
}

impl From<String> for Data {
    fn from(value: String) -> Self {
        Self::String(value)
    }
}
impl From<&str> for Data {
    fn from(value: &str) -> Self {
        Self::String(value.to_owned())
    }
}
impl From<i64> for Data {
    fn from(value: i64) -> Self {
        Self::Int(value)
    }
}
impl From<f64> for Data {
    fn from(value: f64) -> Self {
        Self::Float(value)
    }
}
impl From<bool> for Data {
    fn from(value: bool) -> Self {
        Self::Bool(value)
    }
}