truecalc-core 3.2.0

Formula engine with exact Google Sheets semantics — stateless, embeddable evaluator
Documentation
use crate::eval::coercion::to_bool;
use crate::eval::functions::check_arity;
use crate::types::Value;

/// `NOT(value)` — inverts a boolean value.
///
/// Accepts exactly 1 argument. GS special case: empty text `""` is treated
/// as 0 (false), so `NOT("")` = TRUE. Other non-bool text remains `#VALUE!`.
/// When passed an array, NOT broadcasts element-wise (GS array semantics).
pub fn not_fn(args: &[Value]) -> Value {
    if let Some(err) = check_arity(args, 1, 1) {
        return err;
    }
    not_scalar_or_array(&args[0])
}

fn not_scalar_or_array(v: &Value) -> Value {
    match v {
        Value::Array(items) => {
            let mapped: Vec<Value> = items.iter().map(not_scalar_or_array).collect();
            Value::Array(mapped)
        }
        // GS: NOT("") = TRUE (empty text treated as false/0)
        Value::Text(s) if s.is_empty() => Value::Bool(true),
        _ => match to_bool(v.clone()) {
            Ok(b) => Value::Bool(!b),
            Err(e) => e,
        },
    }
}

#[cfg(test)]
mod tests;