logisheets_controller 0.6.0

the core of LogiSheets
Documentation
use logisheets_parser::ast;

use crate::calc_engine::connector::Connector;

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

pub fn calc<C>(args: Vec<CalcVertex>, fetcher: &mut C) -> CalcVertex
where
    C: Connector,
{
    assert_or_return!(args.len() == 1, ast::Error::Unspecified);
    let first = args.into_iter().next().unwrap();
    match &first {
        CalcVertex::Reference(_) => {
            let values = fetcher.get_calc_value(first);
            let num = match values {
                CalcValue::Scalar(s) => {
                    if is_blank(s) {
                        1.
                    } else {
                        0.
                    }
                }
                CalcValue::Range(r) => {
                    r.into_iter()
                        .fold(0., |prev, v| if is_blank(v) { prev + 1. } else { prev })
                }
                CalcValue::Cube(c) => {
                    c.into_iter()
                        .fold(0., |prev, v| if is_blank(v) { prev + 1. } else { prev })
                }
                CalcValue::Union(_) => unreachable!(),
            };
            CalcVertex::from_number(num)
        }
        _ => CalcVertex::from_error(ast::Error::Unspecified),
    }
}

fn is_blank(v: Value) -> bool {
    match v {
        Value::Blank => true,
        Value::Text(s) => {
            if s.is_empty() {
                true
            } else {
                false
            }
        }
        _ => false,
    }
}