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 GitHubpub(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.