Expand description
Currency and money primitives for the paft ecosystem.
Policy for ISO currencies without a minor-unit exponent (ISO-None):
- If ISO 4217 defines a minor unit for an ISO currency, that exponent is used.
- If ISO is silent (for example
XAU,XDR), the crate consults the metadata registry by ISO code. If metadata is present, itsminor_unitsis used. - If no metadata is registered, operations that require a scale return
MoneyError::MetadataNotFoundwith the offending currency.
Registering metadata overlays:
Use set_currency_metadata to register a human-friendly name and scale:
set_currency_metadata("XAU", "Gold", 3, "XAU", true, Locale::EnUs).unwrap();
set_currency_metadata("XDR", "SDR", 6, "XDR", true, Locale::EnUs).unwrap();
use paft_money::Locale;
set_currency_metadata("XAU", "Gold", 3, "XAU", true, Locale::EnUs).unwrap();
set_currency_metadata("XDR", "SDR", 6, "XDR", true, Locale::EnUs).unwrap();Using metals/funds (recommended defaults):
- Gold
XAU: 3 or 6 decimal places are common; choose per domain needs. - Silver
XAG: similar; often 3. - Platinum
XPT: often 3. - Special Drawing Rights
XDR: 6 is common. These are recommendations; the appropriate scale is domain-driven. Always register the scale you need.
§Decimal backend
The crate exposes a backend-agnostic Decimal type alongside
RoundingStrategy. By default it uses
rust_decimal providing 28 fractional
digits of precision with a fast fixed-size representation. Alternatively,
enabling the bigdecimal feature switches the backend to
bigdecimal for effectively unbounded
precision backed by big integers.
The public API, serde representation (amounts encoded as strings, currencies
as ISO codes), and DataFrame integration remain stable across backends. The
primary trade-offs are performance (the bigdecimal backend may allocate
more often) and precision (see MAX_DECIMAL_PRECISION). Minor-unit scaling
always uses 64-bit integers and therefore remains capped at 18 decimal
places so that 10^scale fits inside an i128 when performing
conversions.
§Quickstart
Create money in ISO currencies, add and subtract safely, serialize with stable representations, and convert via explicit exchange rates.
let price = Money::from_canonical_str("12.34", Currency::Iso(IsoCurrency::USD))?;
let tax = Money::from_canonical_str("1.23", Currency::Iso(IsoCurrency::USD))?;
let total = price.try_add(&tax)?;
assert_eq!(total.format(), "13.57 USD");
// Cross-currency addition is rejected
let eur = Money::from_canonical_str("5", Currency::Iso(IsoCurrency::EUR))?;
assert!(price.try_add(&eur).is_err());§Currency conversion
Use an ExchangeRate to convert with explicit rounding.
let usd = Money::from_canonical_str("10.00", Currency::Iso(IsoCurrency::USD))?;
let rate = ExchangeRate::new(
Currency::Iso(IsoCurrency::USD),
Currency::Iso(IsoCurrency::EUR),
Decimal::from(9) / Decimal::from(10), // 1 USD = 0.9 EUR
)?;
let eur = usd.try_convert_with(&rate, RoundingStrategy::MidpointAwayFromZero)?;
assert_eq!(eur.currency().code(), "EUR");§Serde
Amounts serialize as strings (to avoid exponent notation); currencies serialize as their codes. Example:
let usd = Money::from_canonical_str("12.34", Currency::Iso(IsoCurrency::USD)).unwrap();
let json = serde_json::to_string(&usd).unwrap();
assert_eq!(json, "{\"amount\":\"12.34\",\"currency\":\"USD\"}");§Currency metadata overlays
For ISO codes without a prescribed minor-unit exponent (e.g., XAU, XDR),
register a scale so that rounding and minor-unit conversions are well-defined:
set_currency_metadata("XAU", "Gold", 3, "XAU", true, Locale::EnUs).unwrap();
set_currency_metadata("XDR", "SDR", 6, "XDR", true, Locale::EnUs).unwrap();
use paft_money::Locale;
set_currency_metadata("XAU", "Gold", 3, "XAU", true, Locale::EnUs).unwrap();
set_currency_metadata("XDR", "SDR", 6, "XDR", true, Locale::EnUs).unwrap();§Feature flags
bigdecimal: switch to arbitrary precision decimals (slower, allocates for large values).dataframe: enablesserde/polars/df-deriveintegration for dataframes.panicking-money-ops: implementsAdd/Sub/Mul/DivforMoneythat assert on invalid operations. Prefer thetry_*methods for fallible APIs.money-formatting: opt-in locale-aware formatting and strict parsing forMoney.
When money-formatting is enabled you opt into localized rendering explicitly:
let eur = Money::from_canonical_str("1234.56", Currency::Iso(IsoCurrency::EUR)).unwrap();
assert_eq!(format!("{eur}"), "1234.56 EUR"); // canonical display stays locale-neutral
assert_eq!(eur.format_with_locale(Locale::EnEu).unwrap(), "€1.234,56");
assert_eq!(
Money::from_str_locale("€1.234,56", Currency::Iso(IsoCurrency::EUR), Locale::EnEu)
.unwrap()
.format(),
"1234.56 EUR"
);
assert_eq!(
format!("{}", eur.localized(Locale::EnEu).with_code()),
"€1.234,56 EUR"
);Regardless of backend, serde and the high-level API remain stable; see
MAX_DECIMAL_PRECISION and MAX_MINOR_UNIT_DECIMALS for limits that
affect scaling and minor-unit conversions.
Re-exports§
pub use currency::Currency;pub use currency_utils::MAX_DECIMAL_PRECISION;pub use currency_utils::MAX_MINOR_UNIT_DECIMALS;pub use currency_utils::MinorUnitError;pub use currency_utils::clear_currency_metadata;pub use currency_utils::currency_metadata;pub use currency_utils::set_currency_metadata;pub use currency_utils::try_normalize_currency_code;pub use decimal::RoundingStrategy;pub use error::MoneyError;pub use error::MoneyParseError;pub use money::ExchangeRate;pub use money::Money;
Modules§
- currency
- Currency enumeration with ISO 4217 support and extensible fallback.
- currency_
utils - Utilities and helpers for working with
Currencyvalues. - decimal
- Decimal abstraction toggled by feature flags. Feature-dependent decimal abstraction for paft-money.
- error
- Error types shared across the money crate.
- money
- Money type for representing financial values with currency.
Structs§
- Decimal
Decimalrepresents a 128 bit representation of a fixed-precision decimal number. The finite set of values of typeDecimalare of the form m / 10e, where m is an integer such that -296 < m < 296, and e is an integer between 0 and 28 inclusive.
Enums§
- IsoCurrency
- Re-export
iso_currency::Currencyfor convenience. - Locale
- Supported locales for money formatting/parsing.