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.