hatter 0.1.4

positively mad, zero dependency html templating language
Documentation
use {
    crate::{Args, Fn, OMap, Result, Stmt, Symbol, Value},
    std::{
        collections::{BTreeMap, HashMap},
        rc::Rc,
    },
};

fn val<T: Into<Value>>(i: T) -> Value {
    i.into()
}

macro_rules! into_bool {
    ($type:ty) => {
        impl From<$type> for Value {
            fn from(item: $type) -> Self {
                Value::Bool(item.clone())
            }
        }
    };
}

macro_rules! into_string {
    ($type:ty) => {
        impl From<$type> for Value {
            fn from(item: $type) -> Self {
                Value::String(item.to_string().into())
            }
        }
    };
}

macro_rules! into_number {
    ($type:ty) => {
        impl From<$type> for Value {
            fn from(item: $type) -> Self {
                Value::Number(item.clone().into())
            }
        }
    };
}

macro_rules! into_number_as {
    ($type:ty, $conv:ty) => {
        impl From<$type> for Value {
            fn from(item: $type) -> Self {
                Value::Number((item.clone() as $conv).into())
            }
        }
    };
}

into_string!(String);
into_string!(&String);
into_string!(&&String);

into_number!(i32);
into_number!(&i32);
into_number!(f64);
into_number!(&f64);
into_number_as!(usize, i32);
into_number_as!(&usize, i32);
into_number_as!(isize, i32);
into_number_as!(&isize, i32);

into_bool!(bool);
into_bool!(&bool);

impl From<&Value> for Value {
    fn from(v: &Value) -> Value {
        v.clone()
    }
}

impl<T: Into<Value>> From<Vec<T>> for Value {
    fn from(vec: Vec<T>) -> Self {
        Value::List(vec.into_iter().map(val).collect::<Vec<_>>().into())
    }
}

impl<T: Copy + Into<Value>> From<&Vec<T>> for Value {
    fn from(vec: &Vec<T>) -> Self {
        Value::List(vec.iter().map(|v| (*v).into()).collect::<Vec<_>>().into())
    }
}

impl<T: Copy + Into<Value>> From<&[T]> for Value {
    fn from(vec: &[T]) -> Self {
        Value::List(vec.iter().map(|v| (*v).into()).collect::<Vec<_>>().into())
    }
}

impl From<Symbol> for Value {
    fn from(item: Symbol) -> Self {
        Value::String(item)
    }
}

impl From<&Symbol> for Value {
    fn from(item: &Symbol) -> Self {
        Value::String(item.clone())
    }
}

impl From<&str> for Value {
    fn from(item: &str) -> Self {
        Value::String(item.into())
    }
}

impl From<&&str> for Value {
    fn from(item: &&str) -> Self {
        Value::String(Symbol::from(item))
    }
}

impl<S, V> From<BTreeMap<S, V>> for Value
where
    S: Into<Symbol>,
    V: Into<Value>,
{
    fn from(map: BTreeMap<S, V>) -> Self {
        let mut new = OMap::new();
        for (k, v) in map {
            new.insert(k.into(), v.into());
        }
        Value::Map(new.into())
    }
}

impl<S, V> From<HashMap<S, V>> for Value
where
    S: Into<Symbol>,
    V: Into<Value>,
{
    fn from(map: HashMap<S, V>) -> Self {
        let mut new = OMap::new();
        for (k, v) in map {
            new.insert(k.into(), val(v));
        }
        Value::Map(new.into())
    }
}

impl<T> From<Option<T>> for Value
where
    T: Into<Value>,
{
    fn from(o: Option<T>) -> Self {
        if let Some(v) = o {
            v.into()
        } else {
            Value::None
        }
    }
}

impl From<Stmt> for Value {
    fn from(s: Stmt) -> Value {
        match s {
            Stmt::Value(v) => v,
            Stmt::List(x) => Value::from(x),
            Stmt::Map(x) => Value::from(x),
            _ => unimplemented!(),
        }
    }
}

impl<F> From<F> for Value
where
    F: 'static + std::ops::Fn(Args) -> Result<Value>,
{
    fn from(f: F) -> Value {
        Value::Fn(Fn::Native(rc!(f)))
    }
}

impl<V> From<(V,)> for Value
where
    V: Into<Value>,
{
    fn from(f: (V,)) -> Value {
        Value::List(vec![f.0.into()].into())
    }
}

impl<V1, V2> From<(V1, V2)> for Value
where
    V1: Into<Value>,
    V2: Into<Value>,
{
    fn from(f: (V1, V2)) -> Value {
        Value::List(vec![f.0.into(), f.1.into()].into())
    }
}

impl<V1, V2, V3> From<(V1, V2, V3)> for Value
where
    V1: Into<Value>,
    V2: Into<Value>,
    V3: Into<Value>,
{
    fn from(f: (V1, V2, V3)) -> Value {
        Value::List(vec![f.0.into(), f.1.into(), f.2.into()].into())
    }
}

impl<V1, V2, V3, V4> From<(V1, V2, V3, V4)> for Value
where
    V1: Into<Value>,
    V2: Into<Value>,
    V3: Into<Value>,
    V4: Into<Value>,
{
    fn from(f: (V1, V2, V3, V4)) -> Value {
        Value::List(vec![f.0.into(), f.1.into(), f.2.into(), f.3.into()].into())
    }
}

impl<V1, V2, V3, V4, V5> From<(V1, V2, V3, V4, V5)> for Value
where
    V1: Into<Value>,
    V2: Into<Value>,
    V3: Into<Value>,
    V4: Into<Value>,
    V5: Into<Value>,
{
    fn from(f: (V1, V2, V3, V4, V5)) -> Value {
        Value::List(vec![f.0.into(), f.1.into(), f.2.into(), f.3.into(), f.4.into()].into())
    }
}

impl<V1, V2, V3, V4, V5, V6> From<(V1, V2, V3, V4, V5, V6)> for Value
where
    V1: Into<Value>,
    V2: Into<Value>,
    V3: Into<Value>,
    V4: Into<Value>,
    V5: Into<Value>,
    V6: Into<Value>,
{
    fn from(f: (V1, V2, V3, V4, V5, V6)) -> Value {
        Value::List(
            vec![
                f.0.into(),
                f.1.into(),
                f.2.into(),
                f.3.into(),
                f.4.into(),
                f.5.into(),
            ]
            .into(),
        )
    }
}