Functional Weave
Code in Rust

banking.cheque-amount-words@1.0.0

impl/rust.rs

2,157 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::money_amount::{money, money_from_value, Money};  ← from money.amount ^1.0.0 · built alongside by fune
use super::money_format::format_money;  ← from money.format ^1.0.0 · built alongside by fune
use super::text_number_to_words::amount_in_words;  ← from text.number-to-words ^1.0.0 · built alongside by fune

/// The abbreviation written after pence as figures: 50p, 50c.
fn minor_suffix(currency: &str) -> &'static str {
    if currency == "GBP" {
        "p"
    } else {
        "c"
    }
}

/// The amount lines of a cheque. The words come from text.number-to-words,
/// capitalised and closed with "only" so nothing can be added after them; the
/// figures come from money.format.
///
/// # Panics
/// Panics on an amount of zero or less, an unknown pence style, or a currency
/// text.number-to-words has no words for.
pub fn cheque_amount_words(amount: &Money, pence_style: &str) -> ChequeWording {
    if amount.minor <= 0 {
        panic!("a cheque amount must be greater than zero, received {}", amount.minor);
    }
    let body = match pence_style {
        "words" => amount_in_words(amount),
        "figures" => {
            // The pounds are always in words, even when there are none, so the
            // line never starts with a figure that could be altered.
            let major = amount.minor / 100;
            let minor = amount.minor % 100;
            let mut text = amount_in_words(&money(major * 100, &amount.currency));
            if minor > 0 {
                text.push_str(&format!(" and {}{}", minor, minor_suffix(&amount.currency)));
            }
            text
        }
        other => panic!("unknown pence style \"{}\": expected words or figures", other),
    };
    let mut chars = body.chars();
    let words = match chars.next() {
        Some(first) => format!("{}{} only", first.to_uppercase(), chars.as_str()),
        None => String::from("only"),
    };
    ChequeWording {
        words,
        figures: format_money(amount),
    }
}

pub fn cheque_wording_to_value(w: &ChequeWording) -> Value {
    Value::obj(vec![("words", Value::str(&w.words)), ("figures", Value::str(&w.figures))])
}

pub fn fune_vector(args: &[Value]) -> Value {
    cheque_wording_to_value(&cheque_amount_words(&money_from_value(&args[0]), args[1].as_str()))
}