Immutable money type with decimal precision for financial calculations
| Tier | foundation |
| Role | unclassified (baselined) |
| Path | crates/foundation/money |
| Edition | 2021 |
| Targets | foundation_money |
| Public items | 43 across 1 module |
| Tests | 51 |
What it is for
# foundation-money
Immutable money type with decimal precision for financial calculations.
Core Features
- Exact decimal precision: No floating-point errors
- Immutability: All operations return new values
- Currency enforcement: Operations require matching currencies
- Banker's rounding: Fair rounding for financial calculations
Example
use foundation_money::{Money, dec};
use rust_decimal::Decimal;
// Create money values
let price = Money::usd(dec!(19.99));
let quantity = Decimal::from(3);
let subtotal = price * quantity; // $59.97
// Tax calculation with quantization
let tax_rate = dec!(0.0825); // 8.25%
let tax = (subtotal * tax_rate).quantized(); // Rounds to $4.95
// Currency safety - this would return an error:
// let usd = Money::usd(dec!(100));
// let eur = Money::eur(dec!(100));
// let sum = (usd + eur)?; // CurrencyMismatch error
Capabilities
Decimal
# foundation-money
| Item |
|---|
Decimal :: fn mul(self, money : Money) -> Self::Output |
Money:Money
# foundation-money
| Item |
|---|
pub struct Money |
Money:abs
# foundation-money
| Item |
|---|
Money :: fn abs(& self) -> Self |
Money:add
# foundation-money
| Item |
|---|
Money :: fn add(self, other : Self) -> Self::Output |
Money:amount
# foundation-money
| Item |
|---|
Money :: fn amount(& self) -> Decimal |
Money:aud
# foundation-money
| Item |
|---|
Money :: fn aud(amount : Decimal) -> Self |
Money:btc
# foundation-money
| Item |
|---|
Money :: fn btc(amount : Decimal) -> Self |
Money:cad
# foundation-money
| Item |
|---|
Money :: fn cad(amount : Decimal) -> Self |
Money:chf
# foundation-money
| Item |
|---|
Money :: fn chf(amount : Decimal) -> Self |
Money:cny
# foundation-money
| Item |
|---|
Money :: fn cny(amount : Decimal) -> Self |
Money:currency
# foundation-money
| Item |
|---|
Money :: fn currency(& self) -> & 'static str |
Money:decimals
# foundation-money
| Item |
|---|
Money :: fn decimals(& self) -> u32 |
Money:deserialize
# foundation-money
| Item |
|---|
Money :: fn deserialize <D>(deserializer : D) -> Result <Self, D::Error> where D : Deserializer <'de>, |
Money:eq
# foundation-money
| Item |
|---|
Money :: fn eq(& self, other : & Self) -> bool |
Money:eur
# foundation-money
| Item |
|---|
Money :: fn eur(amount : Decimal) -> Self |
Money:fmt
# foundation-money
| Item |
|---|
Money :: fn fmt(& self, f : & mut fmt::Formatter <'_>) -> fmt::Result |
Money:gbp
# foundation-money
| Item |
|---|
Money :: fn gbp(amount : Decimal) -> Self |
Money:hash
# foundation-money
| Item |
|---|
Money :: fn hash <H : Hasher>(& self, state : & mut H) |
Money:is
# foundation-money
| Item |
|---|
Money :: fn is_positive(& self) -> bool |
Money :: fn is_negative(& self) -> bool |
Money :: fn is_zero(& self) -> bool |
Money:jpy
# foundation-money
| Item |
|---|
Money :: fn jpy(amount : Decimal) -> Self |
Money:krw
# foundation-money
| Item |
|---|
Money :: fn krw(amount : Decimal) -> Self |
Money:mul
# foundation-money
| Item |
|---|
Money :: fn mul(self, scalar : Decimal) -> Self::Output |
Money :: fn mul(self, scalar : i32) -> Self::Output |
Money :: fn mul(self, scalar : i64) -> Self::Output |
Money:mxn
# foundation-money
| Item |
|---|
Money :: fn mxn(amount : Decimal) -> Self |
Money:neg
# foundation-money
| Item |
|---|
Money :: fn neg(self) -> Self::Output |
Money:new
# foundation-money
| Item |
|---|
Money :: fn new(amount : Decimal, currency : & 'static str) -> Self |
Money:quantized
# foundation-money
| Item |
|---|
Money :: fn quantized(& self) -> Self |
Money:same
# foundation-money
| Item |
|---|
Money :: fn same_currency(& self, other : & Self) -> bool |
Money:serialize
# foundation-money
| Item |
|---|
Money :: fn serialize <S>(& self, serializer : S) -> Result <S::Ok, S::Error> where S : Serializer, |
Money:sub
# foundation-money
| Item |
|---|
Money :: fn sub(self, other : Self) -> Self::Output |
Money:try
# foundation-money
| Item |
|---|
Money :: fn try_add(& self, other : & Self) -> Result <Self, MoneyError> |
Money :: fn try_sub(& self, other : & Self) -> Result <Self, MoneyError> |
Money :: fn try_cmp(& self, other : & Self) -> Result <Ordering, MoneyError> |
Money:usd
# foundation-money
| Item |
|---|
Money :: fn usd(amount : Decimal) -> Self |
Money:zero
# foundation-money
| Item |
|---|
Money :: fn zero(currency : & 'static str) -> Self |
MoneyError
# foundation-money
| Item |
|---|
pub enum MoneyError |
MoneyError :: fn currency_mismatch(operation : & 'static str, left : & str, right : & str) -> Self |
i32
# foundation-money
| Item |
|---|
i32 :: fn mul(self, money : Money) -> Self::Output |
i64
# foundation-money
| Item |
|---|
i64 :: fn mul(self, money : Money) -> Self::Output |
currency_decimals (other)
_No module-level documentation is present in the source._
| Item |
|---|
fn get(currency : & str) -> u32 |
How to use it
From this crate's own rustdoc:
use foundation_money::{Money, dec};
use rust_decimal::Decimal;
// Create money values
let price = Money::usd(dec!(19.99));
let quantity = Decimal::from(3);
let subtotal = price * quantity; // $59.97
// Tax calculation with quantization
let tax_rate = dec!(0.0825); // 8.25%
let tax = (subtotal * tax_rate).quantized(); // Rounds to $4.95
// Currency safety - this would return an error:
// let usd = Money::usd(dec!(100));
// let eur = Money::eur(dec!(100));
// let sum = (usd + eur)?; // CurrencyMismatch error
Module structure
foundation_money
currency_decimals
Public surface
`crate root`
| Item | What it is |
|---|---|
pub enum MoneyError | Money-related errors. |
MoneyError :: fn currency_mismatch(operation : & 'static str, left : & str, right : & str) -> Self | Create a currency mismatch error. |
pub struct Money | An immutable monetary amount with currency |
Money :: fn serialize <S>(& self, serializer : S) -> Result <S::Ok, S::Error> where S : Serializer, | — |
Money :: fn deserialize <D>(deserializer : D) -> Result <Self, D::Error> where D : Deserializer <'de>, | — |
Money :: fn new(amount : Decimal, currency : & 'static str) -> Self | Create a new Money value |
Money :: fn usd(amount : Decimal) -> Self | Create a Money value in USD. |
Money :: fn eur(amount : Decimal) -> Self | Create a Money value in EUR. |
Money :: fn gbp(amount : Decimal) -> Self | Create a Money value in GBP. |
Money :: fn jpy(amount : Decimal) -> Self | Create a Money value in JPY. |
Money :: fn mxn(amount : Decimal) -> Self | Create a Money value in MXN. |
Money :: fn cad(amount : Decimal) -> Self | Create a Money value in CAD. |
Money :: fn aud(amount : Decimal) -> Self | Create a Money value in AUD. |
Money :: fn chf(amount : Decimal) -> Self | Create a Money value in CHF. |
Money :: fn cny(amount : Decimal) -> Self | Create a Money value in CNY. |
Money :: fn krw(amount : Decimal) -> Self | Create a Money value in KRW. |
Money :: fn btc(amount : Decimal) -> Self | Create a Money value in BTC. |
Money :: fn zero(currency : & 'static str) -> Self | Create a zero Money value in the given currency. |
Money :: fn amount(& self) -> Decimal | Get the amount. |
Money :: fn currency(& self) -> & 'static str | Get the currency code. |
Money :: fn decimals(& self) -> u32 | Get the number of decimal places for this currency. |
Money :: fn is_positive(& self) -> bool | Check if the amount is positive (> 0). |
Money :: fn is_negative(& self) -> bool | Check if the amount is negative (< 0). |
Money :: fn is_zero(& self) -> bool | Check if the amount is zero. |
Money :: fn abs(& self) -> Self | Get the absolute value. |
Money :: fn quantized(& self) -> Self | Round to the currency's decimal places using banker's rounding |
Money :: fn same_currency(& self, other : & Self) -> bool | Check if this money has the same currency as another. |
Money :: fn try_add(& self, other : & Self) -> Result <Self, MoneyError> | Try to add two Money values (requires matching currencies) |
Money :: fn try_sub(& self, other : & Self) -> Result <Self, MoneyError> | Try to subtract two Money values (requires matching currencies) |
Money :: fn try_cmp(& self, other : & Self) -> Result <Ordering, MoneyError> | Compare two Money values (requires matching currencies) |
Money :: fn fmt(& self, f : & mut fmt::Formatter <'_>) -> fmt::Result | — |
Money :: fn eq(& self, other : & Self) -> bool | — |
Money :: fn hash <H : Hasher>(& self, state : & mut H) | — |
Money :: fn add(self, other : Self) -> Self::Output | — |
Money :: fn sub(self, other : Self) -> Self::Output | — |
Money :: fn neg(self) -> Self::Output | — |
Money :: fn mul(self, scalar : Decimal) -> Self::Output | — |
Decimal :: fn mul(self, money : Money) -> Self::Output | — |
Money :: fn mul(self, scalar : i32) -> Self::Output | — |
i32 :: fn mul(self, money : Money) -> Self::Output | — |
Money :: fn mul(self, scalar : i64) -> Self::Output | — |
i64 :: fn mul(self, money : Money) -> Self::Output | — |
`currency_decimals`
| Item | What it is |
|---|---|
fn get(currency : & str) -> u32 | Get the number of decimal places for a currency. |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
dec | rust_decimal_macros::dec |
Boundary
Depends on no other workspace tier.
Shares tier foundation with 27 other crates: foundation-audit-log, foundation-basemodels, foundation-bounded-io, foundation-conversation-closure, foundation-crypto-sign, foundation-decisioning, foundation-encounter-vocabulary, foundation-fs-metadata, … (27 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | foundation |
| Architectural role (taxonomy) | unclassified (baselined) |
| Location | crates/foundation/money |
| Vocabulary in force (lexicon) | current |
Dependencies
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
rust_decimal | ^1.36 | serde | no | always |
rust_decimal_macros | ^1 | — | no | always |
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
thiserror | ^2 | — | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
tokio-test | ^0.4 | — | no | always |
Build. None.
Depended on by. 12 workspace crates.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR n_application_conversation["application-conversation"] -->|uses| SELF n_application_crm["application-crm"] -->|uses| SELF n_application_money["application-money"] -->|uses| SELF n_domain_billing["domain-billing"] -->|uses| SELF n_domain_catalog["domain-catalog"] -->|uses| SELF n_domain_crm["domain-crm"] -->|uses| SELF n_domain_ledger["domain-ledger"] -->|uses| SELF n_domain_legal_matter["domain-legal-matter"] -->|uses| SELF n_domain_pricing_rules["domain-pricing-rules"] -->|uses| SELF n_operations_control_plane["operations-control-plane"] -->|uses| SELF n_platform_privacy_scan_api["platform-privacy-scan-api"] -->|uses| SELF n_tools_corpus["tools-corpus"] -->|uses| SELF SELF["foundation-money"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
| Feature | Enables | On by default |
|---|---|---|
default | — | yes |
flowchart LR n_default["default"]
Targets
| Kind | Name | Source |
|---|---|---|
| lib | foundation_money | `src/lib.rs` |
Error model
| Error type | Named by |
|---|---|
MoneyError | declared, no public signature returns it |
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | none detected |
| async runtime | none detected |
| database access | none detected |
| network I/O | none detected |
| unsafe code | none detected |
| environment variables | none detected |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
No environment variable is read with a literal name anywhere in this crate. A variable whose key is computed at run time cannot be listed here, and is not claimed to be absent.
Related capabilities
12 workspace crates depend on this one: application-conversation, application-crm, application-money, domain-billing, domain-catalog, domain-crm, domain-ledger, domain-legal-matter, domain-pricing-rules, operations-control-plane, platform-privacy-scan-api, tools-corpus.
Verification
| Kind | Count |
|---|---|
| Unit tests | 51 |
| Integration tests | 0 |
| Examples | 0 |
| Doctests | 1 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
crate root | 2 | 0 | 9 |
currency_decimals | 1 | 0 | 7 |
What the tests establish, by name:
test_abs—src/lib.rstest_add_same_currency—src/lib.rstest_bankers_rounding—src/lib.rstest_bill_split—src/lib.rstest_create_money—src/lib.rstest_currency_constructors—src/lib.rstest_currency_conversion_workflow—src/lib.rstest_currency_decimals—src/lib.rstest_currency_decimals_contract—src/lib.rstest_discount—src/lib.rstest_display—src/lib.rstest_equality—src/lib.rstest_equality_different_currency—src/lib.rstest_error_message_add—src/lib.rstest_error_message_compare—src/lib.rstest_error_message_subtract—src/lib.rstest_hash—src/lib.rstest_hash_observes_amount_and_currency—src/lib.rstest_immutability—src/lib.rstest_is_negative—src/lib.rstest_is_positive—src/lib.rstest_is_zero—src/lib.rstest_money_decimals—src/lib.rstest_multiply_by_decimal—src/lib.rstest_multiply_by_i32—src/lib.rstest_multiply_by_i64—src/lib.rstest_multiply_decimal_by_money—src/lib.rstest_multiply_i32_by_money—src/lib.rstest_negate—src/lib.rstest_negative_results—src/lib.rs- _… 21 more_
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 29 | 43 |
Public modules with a //! block | 0 | 1 |
pie showData
title Public items with rustdoc
"Documented" : 29
"No rustdoc detected" : 14
Metrics
| Metric | Value |
|---|---|
| Rust source files | 1 |
| Source lines | 1012 |
| Code lines | 687 |
| Public API items | 43 |
| Public modules | 1 |
| Tests | 51 |
| Examples | 0 |
| Cargo features | 1 |
| Direct runtime dependencies | 5 |
| Workspace reverse dependencies | 12 |
pie showData
title Public API by kind
"enum" : 1
"function" : 1
"method" : 40
"struct" : 1
pie showData
title Rust source composition
"Code" : 687
"Blank or comment" : 325
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.