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::money_amount::{money_from_value, Money}; ← from money.amount ^1.0.0 · built alongside by fune
use super::money_format_data::CURRENCIES; ← this capability’s own data, compiled from data/currencies.json into the same file by fune build
/// Render a monetary amount as text.
///
/// Not every currency has two decimal places: yen has none, Kuwaiti dinar has
/// three. Dividing by 100 to display an amount is wrong about as often as it
/// is right, so the precision comes from the currency table.
///
/// # Panics
/// Panics if the currency has no entry in the table.
pub fn format_money(amount: &Money) -> String {
let format = match CURRENCIES.iter().find(|c| c.code == amount.currency) {
Some(found) => found,
None => panic!(
"no formatting rules for currency \"{}\"",
amount.currency
),
};
let negative = amount.minor < 0;
let raw = amount.minor.unsigned_abs().to_string();
let width = (format.digits + 1) as usize;
let digits = if raw.len() < width {
"0".repeat(width - raw.len()) + &raw
} else {
raw
};
let split = digits.len() - format.digits as usize;
let whole = &digits[..split];
let fraction = &digits[split..];
let mut grouped = String::new();
for (i, ch) in whole.chars().enumerate() {
if i > 0 && (whole.len() - i) % 3 == 0 {
grouped.push_str(format.group_separator);
}
grouped.push(ch);
}
let number = if format.digits > 0 {
format!("{}{}{}", grouped, format.decimal_separator, fraction)
} else {
grouped
};
let body = if format.symbol_before {
format!("{}{}", format.symbol, number)
} else {
format!("{}{}", number, format.symbol)
};
if negative {
format!("-{}", body)
} else {
body
}
}
pub fn fune_vector(args: &[Value]) -> Value {
Value::Str(format_money(&money_from_value(&args[0])))
}