Shared Rust kernels

ported/dynamic_array_reshape_family

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

coerce_prepared_to_number · 7 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
/// A prepared scalar as a number, by worksheet number coercion (a blank is 0).
pub(crate) fn coerce_prepared_to_number(value: &CalcValue) -> Result<f64, CoercionError> {
    match coerce::number(value)? {
        Numeric::Number(n) => Ok(n),
        Numeric::Decimal(decimal) => Ok(decimal.nearest()?),
    }
}

Used by 14 functions.

scalar_cell · 11 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn scalar_cell(arg: &CalcValue) -> CalcValue {
    match arg.core_ref() {
        CoreRef::Number(n) => CalcValue::number(n),
        CoreRef::Text(t) => CalcValue::text(t.clone()),
        CoreRef::Logical(b) => CalcValue::logical(b),
        CoreRef::Error(code) => CalcValue::error(code),
        CoreRef::Reference(_) => CalcValue::error(WorksheetErrorCode::Value),
        CoreRef::Array(_) => CalcValue::error(WorksheetErrorCode::Value),
        CoreRef::Missing | CoreRef::Empty => CalcValue::empty(),
    }
}

Used by 11 functions.

materialize_array_arg · 6 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn materialize_array_arg(arg: &CalcValue) -> CalcArray {
    match arg.core_ref() {
        CoreRef::Array(array) => array.clone(),
        _ => CalcArray::from_scalar(scalar_cell(arg)),
    }
}

Used by 10 functions.

shape · 6 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn shape(&self) -> ArrayShape {
    match self {
        Self::Array(array) => array.shape(),
        Self::Scalar(_) => ArrayShape { rows: 1, cols: 1 },
    }
}

Used by 12 functions.

get · 7 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn get(&self, row: usize, col: usize) -> Option<&CalcValue> {
    match self {
        Self::Array(array) => array.get(row, col),
        Self::Scalar(cell) if row == 0 && col == 0 => Some(cell),
        Self::Scalar(_) => None,
    }
}

Used by 12 functions.

parse_integer · 12 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
pub(crate) fn parse_integer(prepared: &CalcValue) -> Result<isize, DynamicArrayReshapeEvalError> {
    let raw =
        coerce_prepared_to_number(prepared).map_err(DynamicArrayReshapeEvalError::Preparation)?;
    if !raw.is_finite() {
        return Err(DynamicArrayReshapeEvalError::InvalidCount);
    }
    let truncated = raw.trunc();
    if (truncated - raw).abs() > f64::EPSILON {
        return Err(DynamicArrayReshapeEvalError::InvalidCount);
    }
    Ok(truncated as isize)
}

Used by 9 functions.

parse_positive_integer · 7 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn parse_positive_integer(prepared: &CalcValue) -> Result<usize, DynamicArrayReshapeEvalError> {
    let value = parse_integer(prepared)?;
    if value < 1 {
        return Err(DynamicArrayReshapeEvalError::InvalidCount);
    }
    Ok(value as usize)
}

Used by 3 functions.

parse_bool_like · 13 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn parse_bool_like(prepared: &CalcValue) -> Result<bool, DynamicArrayReshapeEvalError> {
    match prepared.core_ref() {
        CoreRef::Logical(b) => Ok(b),
        CoreRef::Number(n) => Ok(n != 0.0),
        CoreRef::Empty | CoreRef::Missing => Ok(false),
        CoreRef::Error(code) => Err(DynamicArrayReshapeEvalError::Preparation(
            CoercionError::WorksheetError(code),
        )),
        _ => Err(DynamicArrayReshapeEvalError::Preparation(
            CoercionError::UnsupportedValueKind("boolean_like"),
        )),
    }
}

Used by 2 functions.

resolve_selector · 18 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn resolve_selector(index: isize, len: usize) -> Result<usize, DynamicArrayReshapeEvalError> {
    if index == 0 {
        return Err(DynamicArrayReshapeEvalError::InvalidSelector);
    }
    let resolved = if index > 0 {
        (index - 1) as usize
    } else {
        let offset = len as isize + index;
        if offset < 0 {
            return Err(DynamicArrayReshapeEvalError::InvalidSelector);
        }
        offset as usize
    };
    if resolved >= len {
        return Err(DynamicArrayReshapeEvalError::InvalidSelector);
    }
    Ok(resolved)
}

Used by 2 functions.

build_array · 9 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn build_array(
    rows: usize,
    cols: usize,
    cells: Vec<CalcValue>,
) -> Result<CalcValue, DynamicArrayReshapeEvalError> {
    CalcArray::new(ArrayShape { rows, cols }, cells)
        .map(CalcValue::array)
        .ok_or(DynamicArrayReshapeEvalError::EmptyArrayResult)
}

Used by 13 functions.

flatten_cells · 13 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn flatten_cells(array: &CalcArray, by_col: bool) -> Vec<CalcValue> {
    if !by_col {
        return array.iter_row_major().cloned().collect();
    }

    let mut cells = Vec::with_capacity(array.shape().rows * array.shape().cols);
    for col in 0..array.shape().cols {
        for row in 0..array.shape().rows {
            cells.push(array.get(row, col).expect("validated cell").clone());
        }
    }
    cells
}

Used by 4 functions.

take_span · 12 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
pub(crate) fn take_span(len: usize, count: isize) -> Result<(usize, usize), DynamicArrayReshapeEvalError> {
    if count == 0 {
        return Err(DynamicArrayReshapeEvalError::EmptyArrayResult);
    }
    if count > 0 {
        let take = usize::min(count as usize, len);
        Ok((0, take))
    } else {
        let take = usize::min((-count) as usize, len);
        Ok((len - take, len))
    }
}

Used by 2 functions.

drop_span · 11 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
pub(crate) fn drop_span(len: usize, count: isize) -> Result<(usize, usize), DynamicArrayReshapeEvalError> {
    let (start, end) = if count >= 0 {
        (usize::min(count as usize, len), len)
    } else {
        (0, len.saturating_sub((-count) as usize))
    };
    if start >= end {
        return Err(DynamicArrayReshapeEvalError::EmptyArrayResult);
    }
    Ok((start, end))
}

Used by 2 functions.

should_ignore_cell · 12 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn should_ignore_cell(cell: &CalcValue, ignore_mode: usize) -> bool {
    match ignore_mode {
        0 => false,
        1 => matches!(cell.core_ref(), CoreRef::Empty | CoreRef::Missing),
        2 => matches!(cell.core_ref(), CoreRef::Error(_)),
        3 => matches!(
            cell.core_ref(),
            CoreRef::Empty | CoreRef::Missing | CoreRef::Error(_)
        ),
        _ => false,
    }
}

Used by 2 functions.

parse_ignore_mode · 13 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn parse_ignore_mode(arg: Option<&CalcValue>) -> Result<usize, DynamicArrayReshapeEvalError> {
    let Some(arg) = arg else {
        return Ok(0);
    };
    if matches!(arg.core_ref(), CoreRef::Missing | CoreRef::Empty) {
        return Ok(0);
    }
    let mode = parse_integer(arg)?;
    if !(0..=3).contains(&mode) {
        return Err(DynamicArrayReshapeEvalError::InvalidIgnoreMode);
    }
    Ok(mode as usize)
}

Used by 2 functions.

wrap_count · 11 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
/// Wrapping has its own below-one error; other shaping counts keep their existing policy.
fn wrap_count(value: &CalcValue) -> Result<usize, DynamicArrayReshapeEvalError> {
    let number = coerce_prepared_to_number(value)
        .map_err(DynamicArrayReshapeEvalError::Preparation)?;
    if number < 1.0 {
        return Err(DynamicArrayReshapeEvalError::Preparation(
            CoercionError::WorksheetError(WorksheetErrorCode::Num),
        ));
    }
    parse_positive_integer(value)
}

Used by 2 functions.

wrap_vector · 9 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
fn wrap_vector(value: &CalcValue) -> Result<CalcArray, DynamicArrayReshapeEvalError> {
    let source = materialize_array_arg(value);
    if source.shape().rows > 1 && source.shape().cols > 1 {
        return Err(DynamicArrayReshapeEvalError::Preparation(
            CoercionError::UnsupportedValueKind("wrap vector"),
        ));
    }
    Ok(source)
}

Used by 2 functions.

map_dynamic_array_reshape_error_to_ws · 20 lines · calc-func/src/ported/dynamic_array_reshape_family.rs on GitHub
pub fn map_dynamic_array_reshape_error_to_ws(
    error: &DynamicArrayReshapeEvalError,
) -> WorksheetErrorCode {
    match error {
        DynamicArrayReshapeEvalError::ArityMismatch { .. }
        | DynamicArrayReshapeEvalError::InvalidSelector
        | DynamicArrayReshapeEvalError::InvalidCount
        | DynamicArrayReshapeEvalError::InvalidIgnoreMode
        | DynamicArrayReshapeEvalError::InvalidSortOrder
        | DynamicArrayReshapeEvalError::InvalidSortIndex
        | DynamicArrayReshapeEvalError::InvalidIncludeShape
        | DynamicArrayReshapeEvalError::Preparation(CoercionError::UnsupportedValueKind(_))
        | DynamicArrayReshapeEvalError::Preparation(CoercionError::NotModelled) => {
            WorksheetErrorCode::Value
        }
        DynamicArrayReshapeEvalError::Preparation(CoercionError::WorksheetError(code)) => *code,
        DynamicArrayReshapeEvalError::EmptyArrayResult => WorksheetErrorCode::Calc,
        DynamicArrayReshapeEvalError::DimensionTooSmall => WorksheetErrorCode::Value,
    }
}

Used by 13 functions.