Shared Rust kernels

coerce

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

number · 16 lines · calc-func/src/coerce.rs on GitHub
/// The value as a number: a number as it is, TRUE as 1 and FALSE as 0, Empty and Missing as 0,
/// text through [`text_as_decimal`], an error as itself. An array (whose operator lifts over its
/// elements) and a reference are not read here.
pub(crate) fn number(value: &CalcValue) -> Result<Numeric, Stop> {
    if value.is_excel_overflow() {
        return Err(Stop::Error(WorksheetErrorCode::Num));
    }
    match value.core_ref() {
        CoreRef::Number(n) => operand(n).map(Numeric::Number),
        CoreRef::Logical(b) => Ok(Numeric::Number(if b { 1.0 } else { 0.0 })),
        CoreRef::Text(text) => text_as_decimal(text).map(Numeric::Decimal),
        CoreRef::Empty | CoreRef::Missing => Ok(Numeric::Number(0.0)),
        CoreRef::Error(code) => Err(Stop::Error(code)),
        CoreRef::Array(_) | CoreRef::Reference(_) => Err(Stop::NotModelled),
    }
}

Used by 0 functions.

operand · 9 lines · calc-func/src/coerce.rs on GitHub
/// A number as an operand. A non-finite number is not a worksheet value, and Excel's handling of
/// a subnormal one is not modelled; both are refused.
pub(crate) fn operand(n: f64) -> Result<f64, Stop> {
    if n.is_finite() && !n.is_subnormal() {
        Ok(n)
    } else {
        Err(Stop::NotModelled)
    }
}

Used by 0 functions.

logical · 19 lines · calc-func/src/coerce.rs on GitHub
/// The value as a logical: a number is TRUE unless it is 0, a logical as it is, Empty and
/// Missing as FALSE, the text TRUE or FALSE in any ASCII case as that logical, an error as
/// itself. Other text is #VALUE!, digit text included: Excel reads no number from text in a
/// logical position (NOT("1") and IF("1",1,2) are #VALUE! in the captures of dc_fwpz and
/// cfunc_m1_2, and IF over the date label 2020/01/02 in dc_e00t's; OxFunc's
/// `parse_excel_logical_text` records the same rule).
pub(crate) fn logical(value: &CalcValue) -> Result<bool, Stop> {
    match value.core_ref() {
        CoreRef::Number(n) => operand(n).map(|n| n != 0.0),
        CoreRef::Logical(b) => Ok(b),
        CoreRef::Text(text) => match spelled_logical(text) {
            Some(logical) => Ok(logical),
            None => Err(Stop::Error(WorksheetErrorCode::Value)),
        },
        CoreRef::Empty | CoreRef::Missing => Ok(false),
        CoreRef::Error(code) => Err(Stop::Error(code)),
        CoreRef::Array(_) | CoreRef::Reference(_) => Err(Stop::NotModelled),
    }
}

Used by 0 functions.

spelled_logical · 13 lines · calc-func/src/coerce.rs on GitHub
/// The logical that text spells: TRUE or FALSE in any ASCII case, with nothing around it. Read
/// as a logical ([`logical`]) other text is #VALUE! or refused; AND, OR and XOR skip it when it is
/// given directly.
pub(crate) fn spelled_logical(text: &ExcelText) -> Option<bool> {
    let units = text.utf16_code_units();
    if eq_ignore_ascii_case(units, &TRUE_TEXT) {
        Some(true)
    } else if eq_ignore_ascii_case(units, &FALSE_TEXT) {
        Some(false)
    } else {
        None
    }
}

Used by 0 functions.

text · 25 lines · calc-func/src/coerce.rs on GitHub
/// The value as text to concatenate, in UTF-16 code units: text as it is, a number as its text
/// ([`number_text`], Excel's text with `.` as the decimal separator and no column width), TRUE
/// and FALSE as those words, Empty and Missing as empty text, an error as itself. Every finite
/// number has text under that model, including its documented near-tie mismatches. A number
/// qualified as Excel's exponent-carry rounding result uses its measured General
/// rendering. Other nonfinite numbers are refused as not modelled.
pub(crate) fn text(value: &CalcValue) -> Result<Cow<'_, [u16]>, Stop> {
    match value.core_ref() {
        CoreRef::Text(text) => Ok(Cow::Borrowed(text.utf16_code_units())),
        CoreRef::Number(n) if value.is_excel_overflow() => {
            let profile = crate::locale::format_profile(crate::locale::LocaleId::EnZa);
            Ok(Cow::Owned(crate::format::general(&profile, n).encode_utf16().collect()))
        }
        CoreRef::Number(n) if n.is_finite() => number_text::text(n)
            .map(|text| Cow::Owned(text.encode_utf16().collect()))
            .ok_or(Stop::NotModelled),
        CoreRef::Logical(true) => Ok(Cow::Borrowed(&TRUE_TEXT)),
        CoreRef::Logical(false) => Ok(Cow::Borrowed(&FALSE_TEXT)),
        CoreRef::Empty | CoreRef::Missing => Ok(Cow::Borrowed(&[])),
        CoreRef::Error(code) => Err(Stop::Error(code)),
        CoreRef::Number(_) | CoreRef::Array(_) | CoreRef::Reference(_) => {
            Err(Stop::NotModelled)
        }
    }
}

Used by 0 functions.