logisheets_controller 0.6.0

the core of LogiSheets
Documentation
use crate::calc_engine::connector::Connector;

use super::{CalcValue, CalcVertex, Value};
use logisheets_parser::ast;

pub fn calc<C, F>(args: Vec<CalcVertex>, fetcher: &mut C, func: F) -> CalcVertex
where
    C: Connector,
    F: 'static + Fn(&str) -> String,
{
    if args.len() != 1 {
        return CalcVertex::from_error(ast::Error::Unspecified);
    }
    let arg = args.into_iter().next().unwrap();
    let value = fetcher.get_calc_value(arg);
    let v = match value {
        CalcValue::Scalar(s) => CalcValue::Scalar(call(&s, &func)),
        CalcValue::Range(r) => {
            let vec2d = r.map(move |v| call(v, &func));
            CalcValue::Range(vec2d)
        }
        CalcValue::Cube(_) => CalcValue::Scalar(Value::Error(ast::Error::Ref)),
        CalcValue::Union(u) => {
            if u.len() == 1 {
                let arg = *u.into_iter().next().unwrap();
                let v = vec![CalcVertex::Value(arg)];
                if let CalcVertex::Value(value) = calc(v, fetcher, func) {
                    value
                } else {
                    CalcValue::Scalar(Value::Error(ast::Error::Value))
                }
            } else {
                CalcValue::Scalar(Value::Error(ast::Error::Value))
            }
        }
    };
    CalcVertex::Value(v)
}

fn call<F>(value: &Value, func: &F) -> Value
where
    F: Fn(&str) -> String,
{
    match value {
        Value::Blank => Value::Text(func("")),
        Value::Number(n) => Value::Text(func(&n.to_string())),
        Value::Text(t) => Value::Text(func(t)),
        Value::Boolean(b) => {
            if *b {
                Value::Text(func("TRUE"))
            } else {
                Value::Text(func("FALSE"))
            }
        }
        Value::Error(e) => Value::Text(func(e.get_err_str())),
    }
}

pub fn calc_trim<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
    C: Connector,
{
    calc(args, fetcher, |a| a.trim().to_string())
}

pub fn calc_upper<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
    C: Connector,
{
    calc(args, fetcher, |a| a.to_uppercase().to_string())
}

pub fn calc_lower<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
    C: Connector,
{
    calc(args, fetcher, |a| a.to_lowercase().to_string())
}