cellrune 0.1.18

Bounded XLSX/XLSM reading, deterministic calculation, editing, and writing for Rust
Documentation
use std::fmt::Write as _;

use super::{
    ArgumentDefaultValue, ArgumentLayout, ArgumentMode, CallContract, DefaultTrigger,
    MissingArgumentPolicy,
};

impl CallContract {
    pub(in crate::calculation::functions) fn stable_snapshot(self) -> String {
        let mut snapshot = String::new();
        write!(
            snapshot,
            "arity={}:{}:{};layout=",
            self.arity.minimum,
            self.arity
                .maximum
                .map_or_else(|| "none".to_owned(), |value| value.to_string()),
            self.arity.step,
        )
        .expect("writing to String cannot fail");
        write_layout(&mut snapshot, self.layout);
        write!(
            snapshot,
            ";missing={};defaults=",
            missing_policy_name(self.missing)
        )
        .expect("writing to String cannot fail");
        for default in self.defaults {
            write!(
                snapshot,
                "{}:{}:",
                default.position,
                trigger_name(default.trigger)
            )
            .expect("writing to String cannot fail");
            write_default_value(&mut snapshot, default.value);
            snapshot.push(',');
        }
        snapshot.push_str(";repeating_defaults=");
        for default in self.repeating_defaults {
            write!(
                snapshot,
                "{}:{}:{}:",
                default.first_position,
                default.step,
                trigger_name(default.trigger)
            )
            .expect("writing to String cannot fail");
            write_default_value(&mut snapshot, default.value);
            snapshot.push(',');
        }
        snapshot
    }
}

fn write_layout(snapshot: &mut String, layout: ArgumentLayout) {
    match layout {
        ArgumentLayout::Uniform(mode) => {
            write!(snapshot, "uniform:{}", argument_mode_name(mode))
                .expect("writing to String cannot fail");
        }
        ArgumentLayout::Positional(modes) => {
            snapshot.push_str("positional:");
            write_modes(snapshot, modes);
        }
        ArgumentLayout::Repeating {
            leading,
            repeated,
            trailing,
        } => {
            snapshot.push_str("repeating:");
            write_modes(snapshot, leading);
            snapshot.push('/');
            write_modes(snapshot, repeated);
            snapshot.push('/');
            write_modes(snapshot, trailing);
        }
        ArgumentLayout::LetBindings => snapshot.push_str("let_bindings"),
        ArgumentLayout::LambdaDefinition => snapshot.push_str("lambda_definition"),
        ArgumentLayout::ArraysThenCallable => snapshot.push_str("arrays_then_callable"),
    }
}

fn write_modes(snapshot: &mut String, modes: &[ArgumentMode]) {
    for mode in modes {
        snapshot.push_str(argument_mode_name(*mode));
        snapshot.push(',');
    }
}

const fn argument_mode_name(mode: ArgumentMode) -> &'static str {
    match mode {
        ArgumentMode::Scalar => "scalar",
        ArgumentMode::Array => "array",
        ArgumentMode::Reference => "reference",
        ArgumentMode::Callable => "callable",
        ArgumentMode::Deferred => "deferred",
        ArgumentMode::BindingName => "binding_name",
    }
}

const fn trigger_name(trigger: DefaultTrigger) -> &'static str {
    match trigger {
        DefaultTrigger::Absent => "absent",
        DefaultTrigger::Missing => "missing",
        DefaultTrigger::AbsentOrMissing => "absent_or_missing",
    }
}

const fn missing_policy_name(policy: MissingArgumentPolicy) -> &'static str {
    match policy {
        MissingArgumentPolicy::CoerceToBlank => "coerce_to_blank",
        MissingArgumentPolicy::Preserve => "preserve",
    }
}

fn write_default_value(snapshot: &mut String, value: ArgumentDefaultValue) {
    match value {
        ArgumentDefaultValue::Omitted => snapshot.push_str("omitted"),
        ArgumentDefaultValue::Number(number) => {
            write!(snapshot, "number:{:016x}", number.to_bits())
                .expect("writing to String cannot fail");
        }
        ArgumentDefaultValue::Logical(value) => {
            snapshot.push_str(if value {
                "logical:true"
            } else {
                "logical:false"
            });
        }
        ArgumentDefaultValue::NotAvailable => snapshot.push_str("not_available"),
        ArgumentDefaultValue::CalculationError => snapshot.push_str("calculation_error"),
        ArgumentDefaultValue::CallerReference => snapshot.push_str("caller_reference"),
        ArgumentDefaultValue::CriteriaRange => snapshot.push_str("criteria_range"),
        ArgumentDefaultValue::EmptyCollection => snapshot.push_str("empty_collection"),
        ArgumentDefaultValue::IndexColumn => snapshot.push_str("index_column"),
        ArgumentDefaultValue::LookupVector => snapshot.push_str("lookup_vector"),
        ArgumentDefaultValue::NoPadding => snapshot.push_str("no_padding"),
        ArgumentDefaultValue::NoSheetQualifier => snapshot.push_str("no_sheet_qualifier"),
        ArgumentDefaultValue::NoUpperBound => snapshot.push_str("no_upper_bound"),
        ArgumentDefaultValue::AllOccurrences => snapshot.push_str("all_occurrences"),
        ArgumentDefaultValue::SourceRows => snapshot.push_str("source_rows"),
        ArgumentDefaultValue::SourceColumns => snapshot.push_str("source_columns"),
        ArgumentDefaultValue::LinkLocation => snapshot.push_str("link_location"),
    }
}