Functional Weave
Code in Python

charts.shape@1.0.0

impl/rust/bar_rects.rs

2,019 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
use super::math_round_float::round_float;  ← from math.round-float ^1.0.0 · built alongside by fune

/// Rectangles for bars. Edges are rounded to 2 places and sizes are the
/// differences of the rounded edges, so bars that share an edge share it
/// exactly, and a negative bar's height is still positive.
///
/// # Panics
/// Panics on an unknown orientation or a negative thickness.
pub fn bar_rects(bars: &[BarSpec], orientation: &str) -> Vec<Rect> {
    if orientation != "vertical" && orientation != "horizontal" {
        panic!("orientation must be vertical or horizontal, received {}", orientation);
    }
    bars.iter()
        .map(|bar| {
            if !(bar.thickness >= 0.0) {
                panic!("bar thickness must not be negative, received {}", bar.thickness);
            }
            let a0 = round_float(bar.band, 2);
            let a1 = round_float(bar.band + bar.thickness, 2);
            let v0 = round_float(bar.base.min(bar.value), 2);
            let v1 = round_float(bar.base.max(bar.value), 2);
            let across = round_float(a1 - a0, 2);
            let along = round_float(v1 - v0, 2);
            if orientation == "vertical" {
                Rect { x: a0, y: v0, width: across, height: along }
            } else {
                Rect { x: v0, y: a0, width: along, height: across }
            }
        })
        .collect()
}

pub fn rect_to_value(r: &Rect) -> Value {
    Value::obj(vec![
        ("x", Value::Float(r.x)),
        ("y", Value::Float(r.y)),
        ("width", Value::Float(r.width)),
        ("height", Value::Float(r.height)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    let bars: Vec<BarSpec> = args[0]
        .as_arr()
        .iter()
        .map(|b| BarSpec {
            band: b.get("band").as_f64(),
            thickness: b.get("thickness").as_f64(),
            base: b.get("base").as_f64(),
            value: b.get("value").as_f64(),
        })
        .collect();
    Value::Arr(bar_rects(&bars, args[1].as_str()).iter().map(rect_to_value).collect())
}