Functional Weave
Code in Rust

retail.volumetric-weight@1.0.0

impl/rust.rs

2,080 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_div::round_div;  ← from math.round-div ^1.0.0 · built alongside by fune

/// The weight a carrier charges on: the greater of actual and volumetric,
/// rounded up to the carrier's billing step.
///
/// mm³ / (cm³ per kg) is exactly grams, so everything stays in integers.
///
/// # Panics
/// Panics on a dimension below 1 mm, a negative weight, or a divisor or
/// billing step below 1.
pub fn chargeable_weight(
    length_mm: i64,
    width_mm: i64,
    height_mm: i64,
    actual_grams: i64,
    divisor: i64,
    round_up_to_grams: i64,
) -> ChargeableWeight {
    for d in [length_mm, width_mm, height_mm] {
        if d < 1 {
            panic!("dimensions must be 1 mm or more, received {}", d);
        }
    }
    if actual_grams < 0 {
        panic!("actualGrams must not be negative, received {}", actual_grams);
    }
    if divisor < 1 {
        panic!("divisor must be 1 or more, received {}", divisor);
    }
    if round_up_to_grams < 1 {
        panic!("roundUpToGrams must be 1 or more, received {}", round_up_to_grams);
    }
    let volumetric_grams = round_div(length_mm * width_mm * height_mm, divisor, "up");
    let heavier = actual_grams.max(volumetric_grams);
    ChargeableWeight {
        actual_grams,
        volumetric_grams,
        chargeable_grams: round_div(heavier, round_up_to_grams, "up") * round_up_to_grams,
        basis: if volumetric_grams > actual_grams {
            "volumetric".to_string()
        } else {
            "actual".to_string()
        },
    }
}

pub fn chargeable_weight_to_value(w: &ChargeableWeight) -> Value {
    Value::obj(vec![
        ("actualGrams", Value::Int(w.actual_grams)),
        ("volumetricGrams", Value::Int(w.volumetric_grams)),
        ("chargeableGrams", Value::Int(w.chargeable_grams)),
        ("basis", Value::str(&w.basis)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    chargeable_weight_to_value(&chargeable_weight(
        args[0].as_i64(),
        args[1].as_i64(),
        args[2].as_i64(),
        args[3].as_i64(),
        args[4].as_i64(),
        args[5].as_i64(),
    ))
}