Functional Weave
Code in TypeScript

manufacturing.yield-scrap@1.0.0

impl/rust.rs

1,549 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

const MAX_OUTPUT: i64 = ((1i64 << 53) - 1) / 10000;

/// Starts needed for a good output at a yield, rounded up in integers so an
/// exact answer (95 at 95% is 100) never becomes 101 through a float.
///
/// # Panics
/// Panics on a negative or oversized output, or a yield outside 1-10000.
pub fn input_for_yield(required_output: i64, yield_basis_points: i64) -> YieldPlan {
    if !(0..=MAX_OUTPUT).contains(&required_output) {
        panic!(
            "requiredOutput must be a whole number of units from 0 to {}, received {}",
            MAX_OUTPUT, required_output
        );
    }
    if !(1..=10000).contains(&yield_basis_points) {
        panic!("yieldBasisPoints must be a whole number from 1 to 10000, received {}", yield_basis_points);
    }
    let input = round_div(required_output * 10000, yield_basis_points, "up");
    YieldPlan {
        input,
        scrap: input - required_output,
    }
}

pub fn yield_plan_to_value(plan: &YieldPlan) -> Value {
    Value::obj(vec![("input", Value::Int(plan.input)), ("scrap", Value::Int(plan.scrap))])
}

pub fn fune_vector(args: &[Value]) -> Value {
    if let Value::Float(f) = &args[0] {
        panic!("requiredOutput must be a whole number of units from 0 to {}, received {}", MAX_OUTPUT, f);
    }
    if let Value::Float(f) = &args[1] {
        panic!("yieldBasisPoints must be a whole number from 1 to 10000, received {}", f);
    }
    yield_plan_to_value(&input_for_yield(args[0].as_i64(), args[1].as_i64()))
}