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
use super::money_amount::{money, money_from_value, money_to_value, Money}; ← from money.amount ^1.0.0 · built alongside by fune
const MAX_SAFE: i128 = 9_007_199_254_740_991;
/// The selling price that hits a target margin or markup on `cost`.
///
/// Margin divides by the price and markup by the cost, so the same 5000 basis
/// points means 200.00 or 150.00 on a cost of 100.00; the basis is explicit.
///
/// # Panics
/// Panics on a negative cost, a margin of 100% or more, a markup below -100%,
/// an unknown basis, or a calculation beyond 2^53 - 1.
pub fn markup_price(cost: &Money, basis_points: i64, basis: &str, mode: &str) -> Money {
if cost.minor < 0 {
panic!("cost must not be negative, received {}", cost.minor);
}
let (numerator, denominator): (i128, i128) = match basis {
"markup" => {
if basis_points < -10000 {
panic!("a markup of {} basis points gives a negative price", basis_points);
}
(cost.minor as i128 * (10000 + basis_points as i128), 10000)
}
"margin" => {
if basis_points >= 10000 {
panic!("a margin of {} basis points has no finite price", basis_points);
}
(cost.minor as i128 * 10000, 10000 - basis_points as i128)
}
other => panic!("unknown pricing basis \"{}\"", other),
};
// i64 could go further, but TypeScript cannot, and all three must agree.
if numerator > MAX_SAFE {
panic!("the price calculation exceeds 2^53 - 1");
}
money(
round_div(numerator as i64, denominator as i64, mode),
&cost.currency,
)
}
pub fn fune_vector(args: &[Value]) -> Value {
money_to_value(&markup_price(
&money_from_value(&args[0]),
args[1].as_i64(),
args[2].as_str(),
args[3].as_str(),
))
}