typed_money/
lib.rs

1//! # Introduction
2//!
3//! A type-safe money library for Rust that prevents currency mixing bugs at compile time.
4//!
5//! # Features
6//!
7//! - **Type-safe** - Currency mixing prevented at compile time
8//! - **Zero-cost abstractions** - O(1) operations, no runtime overhead
9//! - **100% Safe Rust** - No unsafe code
10//! - **Deterministic** - Uses `rust_decimal` for precise arithmetic
11//! - **Comprehensive** - Full arithmetic, conversions, rounding, and formatting
12//! - **Flexible** - Optional serde support and conversion tracking
13//! - **Internationalization** - 69 currencies with locale-specific formatting
14//! - **Rich metadata** - Country, region, volatility, liquidity ratings
15//! - **Precious metals** - Gold, Silver, Platinum, Palladium, Diamond
16//! - **Base metals** - Copper, Aluminum, Zinc, Nickel
17//! - **Cryptocurrencies** - Major cryptos, stablecoins, DeFi tokens
18//!
19//! # Quick Start
20//!
21//! ```
22//! use typed_money::{Amount, USD, EUR, BTC, ETH, LTC, ADA, USDT, USDC, CAD, CNY, THB, NGN, Rate, RoundingMode};
23//!
24//! // Create amounts
25//! let price = Amount::<USD>::from_major(100);  // $100.00
26//! let tax = Amount::<USD>::from_minor(850);     // $8.50
27//!
28//! // Arithmetic operations
29//! let total = price + tax;  // $108.50
30//! assert_eq!(total.to_minor(), 10850);
31//!
32//! // Currency conversion
33//! let rate = Rate::<USD, EUR>::new(0.85);
34//! let eur_price = price.convert(&rate);  // €85.00
35//!
36//! // Cryptocurrency amounts
37//! let bitcoin = Amount::<BTC>::from_minor(100_000_000);  // 1.00000000 BTC
38//! let ethereum = Amount::<ETH>::from_major(1);           // 1.000000000000000000 ETH
39//! let litecoin = Amount::<LTC>::from_major(10);          // 10.00000000 LTC
40//! let cardano = Amount::<ADA>::from_major(1000);         // 1000.000000 ADA
41//!
42//! // Stablecoin amounts
43//! let tether = Amount::<USDT>::from_major(100);          // 100.000000 USDT
44//! let usd_coin = Amount::<USDC>::from_major(50);         // 50.000000 USDC
45//!
46//! // Multi-currency operations
47//! let cad_amount = Amount::<CAD>::from_major(150);  // C$150.00
48//! let cny_amount = Amount::<CNY>::from_major(700);  // ¥700.00
49//!
50//! // Rounding
51//! let divided = Amount::<USD>::from_major(10) / 3;  // $3.333...
52//! let rounded = divided.round(RoundingMode::HalfUp);  // $3.33
53//! ```
54//!
55//! # Internationalization & Metadata
56//!
57//! ```
58//! use typed_money::{Amount, USD, EUR, BRL, CurrencyMetadata};
59//!
60//! // Access rich currency metadata
61//! let usd_amount = Amount::<USD>::from_major(1234);
62//! println!("Currency: {}", usd_amount.currency_name());     // "US Dollar"
63//! println!("Country: {}", usd_amount.currency_country());   // "United States"
64//! println!("Region: {}", usd_amount.currency_region());     // "North America"
65//! println!("Type: {}", usd_amount.currency_type());         // "Fiat"
66//! println!("Volatility: {}", usd_amount.volatility_rating()); // "Low"
67//! println!("Liquidity: {}", usd_amount.liquidity_rating());   // "High"
68//!
69//! // Locale-specific formatting
70//! let eur_amount = Amount::<EUR>::from_major(1234);
71//! println!("European format: {}", eur_amount); // "€1.234,00 EUR"
72//!
73//! let brl_amount = Amount::<BRL>::from_major(1234);
74//! println!("Brazilian format: {}", brl_amount); // "R$1.234,00 BRL"
75//! ```
76//!
77//! # Precious Metals & Commodities
78//!
79//! ```
80//! use typed_money::{Amount, XAU, XAG, XPT, XPD, XDI, XCU, XAL, CurrencyMetadata};
81//!
82//! // Precious metals with 4 decimal precision
83//! let gold = Amount::<XAU>::from_major(1);        // Au1.0000 XAU
84//! let silver = Amount::<XAG>::from_major(100);    // Ag100.0000 XAG
85//! let platinum = Amount::<XPT>::from_major(1);    // Pt1.0000 XPT
86//! let palladium = Amount::<XPD>::from_major(1);   // Pd1.0000 XPD
87//! let diamond = Amount::<XDI>::from_major(1);     // Di1.0000 XDI
88//!
89//! // Base metals
90//! let copper = Amount::<XCU>::from_major(1000);   // Cu1000.0000 XCU
91//! let aluminum = Amount::<XAL>::from_major(1000); // Al1000.0000 XAL
92//!
93//! // Access commodity metadata
94//! println!("Gold region: {}", gold.currency_region());     // "Worldwide"
95//! println!("Gold type: {}", gold.currency_type());         // "Commodity"
96//! println!("Gold volatility: {}", gold.volatility_rating()); // "Medium"
97//! ```
98//!
99//! # Type Safety
100//!
101//! The library prevents currency mixing at compile time:
102//!
103//! ```compile_fail
104//! use typed_money::{Amount, USD, EUR};
105//!
106//! let usd = Amount::<USD>::from_major(100);
107//! let eur = Amount::<EUR>::from_major(85);
108//!
109//! // This won't compile - type mismatch!
110//! let invalid = usd + eur;
111//! ```
112//!
113//! # Supported Currencies
114//!
115//! Built-in currencies include:
116//!
117//! ## Major Fiat Currencies
118//! - **USD** - United States Dollar (2 decimals)
119//! - **EUR** - Euro (2 decimals)
120//! - **GBP** - British Pound Sterling (2 decimals)
121//! - **JPY** - Japanese Yen (0 decimals)
122//! - **CAD** - Canadian Dollar (2 decimals)
123//! - **CHF** - Swiss Franc (2 decimals)
124//! - **AUD** - Australian Dollar (2 decimals)
125//! - **NZD** - New Zealand Dollar (2 decimals)
126//!
127//! ## Asian Currencies
128//! - **CNY** - Chinese Yuan (2 decimals)
129//! - **KRW** - South Korean Won (0 decimals)
130//! - **SGD** - Singapore Dollar (2 decimals)
131//! - **HKD** - Hong Kong Dollar (2 decimals)
132//! - **TWD** - New Taiwan Dollar (2 decimals)
133//! - **INR** - Indian Rupee (2 decimals)
134//!
135//! ## European Currencies
136//! - **SEK** - Swedish Krona (2 decimals)
137//! - **NOK** - Norwegian Krone (2 decimals)
138//! - **DKK** - Danish Krone (2 decimals)
139//! - **PLN** - Polish Złoty (2 decimals)
140//! - **CZK** - Czech Koruna (2 decimals)
141//! - **HUF** - Hungarian Forint (0 decimals)
142//!
143//! ## American Currencies
144//! - **BRL** - Brazilian Real (2 decimals)
145//! - **MXN** - Mexican Peso (2 decimals)
146//! - **ARS** - Argentine Peso (2 decimals)
147//! - **CLP** - Chilean Peso (0 decimals)
148//!
149//! ## African/Middle Eastern Currencies
150//! - **ZAR** - South African Rand (2 decimals)
151//! - **EGP** - Egyptian Pound (2 decimals)
152//! - **AED** - United Arab Emirates Dirham (2 decimals)
153//! - **SAR** - Saudi Riyal (2 decimals)
154//! - **ILS** - Israeli Shekel (2 decimals)
155//! - **TRY** - Turkish Lira (2 decimals)
156//!
157//! ## Regional Currencies
158//!
159//! ### European Regional
160//! - **RON** - Romanian Leu (2 decimals)
161//! - **BGN** - Bulgarian Lev (2 decimals)
162//! - **HRK** - Croatian Kuna (2 decimals)
163//! - **RSD** - Serbian Dinar (2 decimals)
164//! - **UAH** - Ukrainian Hryvnia (2 decimals)
165//!
166//! ### Asian Regional
167//! - **THB** - Thai Baht (2 decimals)
168//! - **MYR** - Malaysian Ringgit (2 decimals)
169//! - **IDR** - Indonesian Rupiah (0 decimals)
170//! - **PHP** - Philippine Peso (2 decimals)
171//! - **VND** - Vietnamese Dong (0 decimals)
172//!
173//! ### American Regional
174//! - **COP** - Colombian Peso (2 decimals)
175//! - **PEN** - Peruvian Sol (2 decimals)
176//! - **UYU** - Uruguayan Peso (2 decimals)
177//! - **BOB** - Bolivian Boliviano (2 decimals)
178//! - **PYG** - Paraguayan Guarani (0 decimals)
179//!
180//! ### African Regional
181//! - **NGN** - Nigerian Naira (2 decimals)
182//! - **KES** - Kenyan Shilling (2 decimals)
183//! - **GHS** - Ghanaian Cedi (2 decimals)
184//! - **MAD** - Moroccan Dirham (2 decimals)
185//! - **TND** - Tunisian Dinar (3 decimals)
186//!
187//! ### Middle Eastern Regional
188//! - **QAR** - Qatari Riyal (2 decimals)
189//! - **KWD** - Kuwaiti Dinar (3 decimals)
190//! - **BHD** - Bahraini Dinar (3 decimals)
191//! - **OMR** - Omani Rial (3 decimals)
192//! - **JOD** - Jordanian Dinar (3 decimals)
193//!
194//! ## Cryptocurrencies
195//! - **BTC** - Bitcoin (8 decimals)
196//! - **ETH** - Ethereum (18 decimals)
197//!
198//! ## Precious Metals
199//! - **XAU** - Gold (4 decimals - troy ounces)
200//! - **XAG** - Silver (4 decimals - troy ounces)
201//! - **XPT** - Platinum (4 decimals - troy ounces)
202//! - **XPD** - Palladium (4 decimals - troy ounces)
203//! - **XDI** - Diamond (4 decimals - carats)
204//!
205//! ## Base Metals
206//! - **XCU** - Copper (4 decimals - metric tons)
207//! - **XAL** - Aluminum (4 decimals - metric tons)
208//! - **XZN** - Zinc (4 decimals - metric tons)
209//! - **XNI** - Nickel (4 decimals - metric tons)
210//!
211//! # Feature Flags
212//!
213//! - `use_rust_decimal` (default) - Use rust_decimal backend
214//! - `use_bigdecimal` - Use bigdecimal backend (alternative)
215//! - `serde_support` - Enable serde serialization
216//! - `conversion_tracking` - Enable conversion tracking/logging
217//!
218//! # Examples
219//!
220//! The library includes comprehensive examples demonstrating various use cases.
221//! Run any example with `cargo run --example <name>`:
222//!
223//! ### [`basic_usage`](https://github.com/ricardoferreirades/typed-money/blob/main/examples/basic_usage.rs)
224//! Fundamental operations including:
225//! - Creating amounts from major/minor units
226//! - Arithmetic operations (add, subtract, multiply, divide)
227//! - Comparisons between amounts
228//! - Working with different currencies
229//! - Real-world shopping cart example
230//!
231//! ```bash
232//! cargo run --example basic_usage
233//! ```
234//!
235//! ### [`conversions`](https://github.com/ricardoferreirades/typed-money/blob/main/examples/conversions.rs)
236//! Currency conversion examples:
237//! - Basic conversion with exchange rates
238//! - Inverse rates
239//! - Chained conversions (USD → EUR → GBP)
240//! - Rate metadata for auditability
241//! - International payment processing
242//!
243//! ```bash
244//! cargo run --example conversions
245//! ```
246//!
247//! ### [`rounding`](https://github.com/ricardoferreirades/typed-money/blob/main/examples/rounding.rs)
248//! Demonstrates all 7 rounding modes:
249//! - HalfUp, HalfDown, HalfEven (Banker's)
250//! - Up, Down, Floor, Ceiling
251//! - Edge cases with negative numbers
252//! - Tax and interest calculations
253//! - When to use each mode
254//!
255//! ```bash
256//! cargo run --example rounding
257//! ```
258//!
259//! ### [`custom_currency`](https://github.com/ricardoferreirades/typed-money/blob/main/examples/custom_currency.rs)
260//! Defining custom currencies:
261//! - Custom fiat currencies (CAD, CHF, AUD)
262//! - Cryptocurrencies (DOGE)
263//! - Game currencies (GOLD, GEMS)
264//! - Loyalty points systems
265//! - Multi-currency wallets
266//!
267//! ```bash
268//! cargo run --example custom_currency
269//! ```
270//!
271//! ### [`error_handling`](https://github.com/ricardoferreirades/typed-money/blob/main/examples/error_handling.rs)
272//! Comprehensive error handling:
273//! - Parse errors with recovery
274//! - Precision errors and normalization
275//! - Invalid rate validation
276//! - Error propagation with `?`
277//! - User input validation
278//!
279//! ```bash
280//! cargo run --example error_handling
281//! ```
282//!
283//! ### [`serialization`](https://github.com/ricardoferreirades/typed-money/blob/main/examples/serialization.rs)
284//! Serde integration (requires `serde_support` feature):
285//! - JSON serialization/deserialization
286//! - Struct serialization with amounts
287//! - Collections and multi-currency data
288//! - API response handling
289//! - Persistence examples
290//!
291//! ```bash
292//! cargo run --example serialization --features serde_support
293//! ```
294
295#![forbid(unsafe_code)]
296#![warn(missing_docs)]
297#![warn(clippy::all)]
298
299// Ensure exactly one decimal backend is enabled
300#[cfg(not(any(feature = "use_rust_decimal", feature = "use_bigdecimal")))]
301compile_error!("Either 'use_rust_decimal' or 'use_bigdecimal' feature must be enabled");
302
303#[cfg(all(feature = "use_rust_decimal", feature = "use_bigdecimal"))]
304compile_error!("Only one decimal backend can be enabled at a time");
305
306mod amount;
307mod currency;
308mod error;
309mod rate;
310mod rounding;
311
312#[cfg(feature = "conversion_tracking")]
313pub mod conversion_tracking;
314
315pub use amount::{Amount, CurrencyMetadata};
316pub use currency::{
317    // Core currencies
318    Currency,
319    // Currency metadata types
320    CurrencyType,
321    LiquidityRating,
322    SymbolPosition,
323    VolatilityRating,
324    AAVE,
325    // Major Cryptocurrencies
326    ADA,
327    AED,
328    ARS,
329    AUD,
330    BCH,
331    // European Regional Currencies
332    BGN,
333    // Middle Eastern Regional Currencies
334    BHD,
335    // American Regional Currencies
336    BOB,
337    // American Currencies
338    BRL,
339    BTC,
340    // Stablecoins
341    BUSD,
342    // Major Fiat Currencies
343    CAD,
344    CHF,
345    CLP,
346    // Asian Currencies
347    CNY,
348    // DeFi Tokens
349    COMP,
350    COP,
351    CZK,
352    DAI,
353    DKK,
354    DOT,
355    EGP,
356    ETH,
357    EUR,
358    GBP,
359    // African Regional Currencies
360    GHS,
361    HKD,
362    HRK,
363    HUF,
364    // Asian Regional Currencies
365    IDR,
366    ILS,
367    INR,
368    JOD,
369    JPY,
370    KES,
371    KRW,
372    KWD,
373    LINK,
374    LTC,
375    MAD,
376    MKR,
377    MXN,
378    MYR,
379    NGN,
380    NOK,
381    NZD,
382    OMR,
383    PEN,
384    PHP,
385    PLN,
386    PYG,
387    QAR,
388    RON,
389    RSD,
390    SAR,
391    // European Currencies
392    SEK,
393    SGD,
394    SUSHI,
395    THB,
396    TND,
397    TRY,
398    TWD,
399    UAH,
400    UNI,
401    USD,
402    USDC,
403    USDT,
404    UYU,
405    VND,
406    XAG,
407    XAL,
408    // Precious Metals
409    XAU,
410    // Base Metals
411    XCU,
412    XDI,
413    XNI,
414    XPD,
415    XPT,
416    XRP,
417    XZN,
418    YFI,
419    // African/Middle Eastern Currencies
420    ZAR,
421};
422pub use error::{MoneyError, MoneyResult};
423pub use rate::Rate;
424pub use rounding::RoundingMode;