Functional Weave
Code in Python

charts.shape@1.0.1

impl/rust/step_path.rs

1,592 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::charts_shape_line_path::{point_runs, points_from_value, svg_pair};  ← linePath, another function of this group · built into the same file, even by a slim install

/// A step line as SVG path data, as d3.curveStepBefore, d3.curveStep and
/// d3.curveStepAfter draw it: horizontal then vertical moves only.
///
/// # Panics
/// Panics on a position other than before, middle or after.
pub fn step_path(points: &[Point], position: &str) -> String {
    let t = match position {
        "before" => 0.0,
        "middle" => 0.5,
        "after" => 1.0,
        other => panic!("step position must be before, middle or after, received {}", other),
    };
    let mut out = String::new();
    for run in point_runs(points) {
        out.push('M');
        out.push_str(&svg_pair(run[0].0, run[0].1));
        for i in 1..run.len() {
            let (px, py) = run[i - 1];
            let (x, y) = run[i];
            if t <= 0.0 {
                out.push_str(&format!("L{}L{}", svg_pair(px, y), svg_pair(x, y)));
            } else {
                // d3's own expression, so the midpoint rounds as d3's does.
                let x1 = px * (1.0 - t) + x * t;
                out.push_str(&format!("L{}L{}", svg_pair(x1, py), svg_pair(x1, y)));
            }
        }
        if t > 0.0 && t < 1.0 && run.len() >= 2 {
            let (lx, ly) = run[run.len() - 1];
            out.push('L');
            out.push_str(&svg_pair(lx, ly));
        }
        if run.len() == 1 {
            out.push('Z');
        }
    }
    out
}

pub fn fune_vector(args: &[Value]) -> Value {
    Value::str(&step_path(&points_from_value(&args[0]), args[1].as_str()))
}