Functional Weave
Code in Rust

charts.extent@1.0.1

impl/rust.rs

1,316 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one

/// [min, max] of a series, skipping gaps (`None`); `None` when nothing is left.
///
/// # Panics
/// Panics on a value that is not finite.
pub fn extent(values: &[Option<f64>]) -> Option<Vec<f64>> {
    let mut range: Option<(f64, f64)> = None;
    for v in values.iter().flatten() {
        if !v.is_finite() {
            panic!("values must be finite numbers or null, received {}", v);
        }
        range = Some(match range {
            None => (*v, *v),
            Some((lo, hi)) => (if *v < lo { *v } else { lo }, if *v > hi { *v } else { hi }),
        });
    }
    range.map(|(lo, hi)| vec![lo, hi])
}

pub fn fune_vector(args: &[Value]) -> Value {
    // A value the typed signature cannot hold (text, true) is refused with the
    // wording TypeScript and Python use, rather than read as 0.
    let values: Vec<Option<f64>> = args[0]
        .as_arr()
        .iter()
        .map(|v| match v {
            Value::Null => None,
            Value::Int(_) | Value::Float(_) => Some(v.as_f64()),
            _ => panic!("values must be finite numbers or null, received a value that is not a number"),
        })
        .collect();
    match extent(&values) {
        Some(r) => Value::Arr(r.into_iter().map(Value::Float).collect()),
        None => Value::Null,
    }
}