Shared Rust kernels

catalogue/kit

All modules · quoted at commit 9e1884369a67 of DnaCalc/DnaCalc. Comments are the source's own.

num · 4 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Argument `index` as a number, through worksheet number coercion.
pub(super) fn num(site: &Site<'_>, arguments: &[CalcValue], index: usize) -> Step<f64> {
    site.number_argument(index, &arguments[index])
}

Used by 0 functions.

reject_logical · 9 lines · calc-func/src/catalogue/kit.rs on GitHub
/// A kind check for positions whose recorded numeric admission excludes logicals.
/// The caller keeps its existing number, blank, missing and error readers.
pub(super) fn reject_logical(value: &CalcValue) -> Step<()> {
    if matches!(value.core_ref(), CoreRef::Logical(_)) {
        fail(WorksheetErrorCode::Value)
    } else {
        Ok(())
    }
}

Used by 0 functions.

num_without_logical · 5 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Number coercion at a position whose measured admission excludes logicals.
pub(super) fn num_without_logical(site: &Site<'_>, arguments: &[CalcValue], index: usize) -> Step<f64> {
    reject_logical(&arguments[index])?;
    num(site, arguments, index)
}

Used by 0 functions.

checked_date_serial · 9 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Validate a date argument before reading the next argument. Negative fractions are
/// rejected before truncation; the existing calendar validator supplies the upper bound.
pub(super) fn checked_date_serial(serial: f64) -> Step<f64> {
    if serial < 0.0 {
        return fail(WorksheetErrorCode::Num);
    }
    crate::ported::date_kernels::serial_from_number(serial).map_err(Exit::Error)?;
    Ok(serial)
}

Used by 0 functions.

num_with_subnormal · 12 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Number coercion for a kernel that implements its own measured subnormal input policy.
/// Keep the ordinary coercions and refusals for every other kind of value.
pub(super) fn num_with_subnormal(
    site: &Site<'_>,
    arguments: &[CalcValue],
    index: usize,
) -> Step<f64> {
    match arguments[index].core_ref() {
        CoreRef::Number(n) if n.is_subnormal() => Ok(n),
        _ => num(site, arguments, index),
    }
}

Used by 0 functions.

opt · 14 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Argument `index` as a number, or `default` when the call does not reach it. An argument the
/// call leaves empty (`f(1,)`) is read as 0, as coercion reads it.
pub(super) fn opt(
    site: &Site<'_>,
    arguments: &[CalcValue],
    index: usize,
    default: f64,
) -> Step<f64> {
    if index < arguments.len() {
        num(site, arguments, index)
    } else {
        Ok(default)
    }
}

Used by 0 functions.

given · 6 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Whether argument `index` was supplied and not left empty.
pub(super) fn given(arguments: &[CalcValue], index: usize) -> bool {
    arguments
        .get(index)
        .is_some_and(|value| !value.is_missing())
}

Used by 0 functions.

flag · 4 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Argument `index` as a logical, through worksheet logical coercion.
pub(super) fn flag(site: &Site<'_>, arguments: &[CalcValue], index: usize) -> Step<bool> {
    site.argument(index, coerce::logical(&arguments[index]))
}

Used by 0 functions.

opt_flag · 13 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Argument `index` as a logical, or `default` when the call does not reach it.
pub(super) fn opt_flag(
    site: &Site<'_>,
    arguments: &[CalcValue],
    index: usize,
    default: bool,
) -> Step<bool> {
    if index < arguments.len() {
        flag(site, arguments, index)
    } else {
        Ok(default)
    }
}

Used by 0 functions.

text · 6 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Argument `index` as text, through worksheet text coercion. Text that is not valid UTF-16 is
/// refused, since the ported kernels read Rust strings.
pub(super) fn text(site: &Site<'_>, arguments: &[CalcValue], index: usize) -> Step<String> {
    let units = site.argument(index, coerce::text(&arguments[index]))?;
    String::from_utf16(&units).map_err(|_| site.not_modelled(Some(index)))
}

Used by 0 functions.

text_arg · 6 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Argument `index` as Excel text (UTF-16 code units, any), through worksheet text coercion: for
/// the ported text kernels, which read [`ExcelText`] rather than Rust strings.
pub(super) fn text_arg(site: &Site<'_>, arguments: &[CalcValue], index: usize) -> Step<ExcelText> {
    let units = site.argument(index, coerce::text(&arguments[index]))?;
    Ok(ExcelText::from_utf16_code_units(units.into_owned()))
}

Used by 0 functions.

out · 8 lines · calc-func/src/catalogue/kit.rs on GitHub
/// A ported kernel's number result: its worksheet error, or the number published by the number
/// rule (non-finite is #NUM!, a subnormal is refused).
pub(super) fn out(site: &Site<'_>, result: Result<f64, WorksheetErrorCode>) -> Step<CalcValue> {
    match result {
        Ok(n) => site.number(n),
        Err(code) => Err(Exit::Error(code)),
    }
}

Used by 0 functions.

out_with_subnormal · 11 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Publish a kernel's measured subnormal result as a number; other outcomes use `out`.
/// The caller still runs the family's numeric-mode check before calculating.
pub(super) fn out_with_subnormal(
    site: &Site<'_>,
    result: Result<f64, WorksheetErrorCode>,
) -> Step<CalcValue> {
    match result {
        Ok(n) if n.is_subnormal() => Ok(CalcValue::number(n)),
        other => out(site, other),
    }
}

Used by 0 functions.

out_text · 4 lines · calc-func/src/catalogue/kit.rs on GitHub
/// A ported kernel's text result.
pub(super) fn out_text(result: Result<ExcelText, WorksheetErrorCode>) -> Step<CalcValue> {
    result.map(CalcValue::text).map_err(Exit::Error)
}

Used by 0 functions.

text_value · 4 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Text as a worksheet value.
pub(super) fn text_value(text: &str) -> CalcValue {
    CalcValue::text(ExcelText::from_interop_assignment(text))
}

Used by 0 functions.

fail · 4 lines · calc-func/src/catalogue/kit.rs on GitHub
/// A worksheet error as a step.
pub(super) fn fail<T>(code: WorksheetErrorCode) -> Step<T> {
    Err(Exit::Error(code))
}

Used by 0 functions.

scalar_error · 8 lines · calc-func/src/catalogue/kit.rs on GitHub
/// A formed scalar error, preserving the distinction from a callable or a held array/reference
/// error. The caller decides where this error precedes its own argument validation.
pub(super) fn scalar_error(value: &CalcValue) -> Step<()> {
    match value.core_ref() {
        CoreRef::Error(code) if value.callable_value().is_none() => fail(code),
        _ => Ok(()),
    }
}

Used by 0 functions.

out_matrix · 18 lines · calc-func/src/catalogue/kit.rs on GitHub
/// A matrix result as an array value; each element is published by the number rule.
pub(super) fn out_matrix(site: &Site<'_>, rows: &[Vec<f64>]) -> Step<CalcValue> {
    let mut cells = Vec::with_capacity(rows.len());
    for row in rows {
        let mut out_row = Vec::with_capacity(row.len());
        for &n in row {
            out_row.push(match site.number(n) {
                Ok(value) => value,
                Err(Exit::Error(code)) => CalcValue::error(code),
                Err(fault) => return Err(fault),
            });
        }
        cells.push(out_row);
    }
    CalcArray::from_rows(cells)
        .map(CalcValue::array)
        .ok_or_else(|| site.not_modelled(None))
}

Used by 0 functions.

numbers · 18 lines · calc-func/src/catalogue/kit.rs on GitHub
/// The numbers the arguments `from..` give an aggregate that reads held values by `held`, in the
/// reading order: a direct argument through number coercion, a held value as the aggregate rule
/// says (see the aggregate family). The first error is the result.
pub(super) fn numbers(
    site: &Site<'_>,
    arguments: &[CalcValue],
    from: usize,
    to: usize,
    services: &mut EvalServices<'_>,
    held: Held,
) -> Step<Vec<f64>> {
    let mut found = Vec::new();
    aggregate::each_number(site, &arguments[from..to], services, held, &mut |n| {
        found.push(n);
        Ok(())
    })?;
    Ok(found)
}

Used by 0 functions.

values · 17 lines · calc-func/src/catalogue/kit.rs on GitHub
/// Every value of the arguments `from..to` in the reading order, with whether it is held (a cell
/// of a reference or an element of an array) or direct.
pub(super) fn values(
    site: &Site<'_>,
    arguments: &[CalcValue],
    from: usize,
    to: usize,
    services: &mut EvalServices<'_>,
    visit: &mut dyn FnMut(bool, &CalcValue) -> Step<()>,
) -> Step<()> {
    aggregate::each_value(
        site,
        &arguments[from..to],
        services,
        &mut |_, origin, value| visit(origin != Origin::Direct, value),
    )
}

Used by 0 functions.

grid · 55 lines · calc-func/src/catalogue/kit.rs on GitHub
pub(super) fn grid(
    site: &Site<'_>,
    arguments: &[CalcValue],
    index: usize,
    services: &mut EvalServices<'_>,
) -> Step<Grid> {
    let argument = &arguments[index];
    match argument.core_ref() {
        CoreRef::Reference(reference) => {
            let [area] = reference.areas() else {
                return Err(site.not_modelled(Some(index)));
            };
            if area.cell_count() > GRID_LIMIT {
                return Err(site.not_modelled(Some(index)));
            }
            let (rows, cols) = (area.row_count() as usize, area.column_count() as usize);
            let first = area.first();
            let mut cells = vec![CalcValue::empty(); rows * cols];
            let cells_reader = aggregate::reader(site, services, index)?;
            aggregate::read_reference(
                site,
                cells_reader,
                reference,
                index,
                &mut |_, key, value| {
                    let at = (key.row() - first.row()) as usize * cols
                        + (key.column() - first.column()) as usize;
                    cells[at] = value.clone();
                    Ok(())
                },
            )?;
            Ok(Grid {
                rows,
                cols,
                cells,
                held: true,
            })
        }
        CoreRef::Array(array) => {
            let shape = array.shape();
            Ok(Grid {
                rows: shape.rows,
                cols: shape.cols,
                cells: array.iter_row_major().cloned().collect(),
                held: true,
            })
        }
        _ => Ok(Grid {
            rows: 1,
            cols: 1,
            cells: vec![argument.clone()],
            held: false,
        }),
    }
}

Used by 0 functions.

pairs · 28 lines · calc-func/src/catalogue/kit.rs on GitHub
/// The pairs of numbers two arguments hold at the same positions, for the paired statistics:
/// arguments of different cell counts are #N/A; a position where either holds no number is
/// skipped (direct scalars follow `scalars`); the first error in reading order
/// (the first argument's before the second's at a position) is the result.
pub(super) fn pairs(
    site: &Site<'_>,
    arguments: &[CalcValue],
    x: usize,
    y: usize,
    scalars: PairScalars,
    services: &mut EvalServices<'_>,
) -> Step<Vec<(f64, f64)>> {
    let left = grid(site, arguments, x, services)?;
    let right = grid(site, arguments, y, services)?;
    if left.cells.len() != right.cells.len() {
        return fail(WorksheetErrorCode::NA);
    }
    let mut found = Vec::new();
    for (a, b) in left.cells.iter().zip(&right.cells) {
        let skip_nonnumeric = matches!(scalars, PairScalars::SkipNonnumeric);
        let a = grid_number(site, x, left.held || skip_nonnumeric, a)?;
        let b = grid_number(site, y, right.held || skip_nonnumeric, b)?;
        if let (Some(a), Some(b)) = (a, b) {
            found.push((a, b));
        }
    }
    Ok(found)
}

Used by 0 functions.