pub struct Rate<From: Currency, To: Currency> {
rate: Decimal,
metadata_timestamp_unix_secs: Option<u64>,
metadata_source: Option<&'static str>,
_from: PhantomData<From>,
_to: PhantomData<To>,
}Expand description
An exchange rate from one currency to another.
Exchange rates are immutable after construction and use phantom types to ensure type-safe conversions at compile time.
§Type Parameters
From- The source currencyTo- The target currency
§Examples
use typed_money::{Rate, USD, EUR};
// Create a rate: 1 USD = 0.85 EUR
let rate = Rate::<USD, EUR>::new(0.85);§Immutability
Rates are immutable after creation to ensure auditability and prevent accidental modifications that could lead to financial errors.
Fields§
§rate: DecimalThe exchange rate value (always positive)
metadata_timestamp_unix_secs: Option<u64>Optional UNIX timestamp (seconds) representing when the rate was observed
Kept optional to avoid forcing callers to provide a timestamp. Using a
primitive preserves Copy and avoids allocations.
metadata_source: Option<&'static str>Optional static source identifier for auditability (e.g., “ECB”, “Manual”)
Using &'static str preserves Copy. Callers can pass string literals
for simple source tagging without allocations.
_from: PhantomData<From>Phantom data for source currency (zero runtime cost)
_to: PhantomData<To>Phantom data for target currency (zero runtime cost)
Implementations§
Source§impl<From: Currency, To: Currency> Rate<From, To>
impl<From: Currency, To: Currency> Rate<From, To>
Sourcepub fn try_new(rate: f64) -> MoneyResult<Self>
pub fn try_new(rate: f64) -> MoneyResult<Self>
Tries to create a new exchange rate from a floating-point value.
Returns an error if the rate is zero, negative, NaN, or infinite.
§Examples
use typed_money::{Rate, USD, EUR};
let rate = Rate::<USD, EUR>::try_new(0.85)?; // 1 USD = 0.85 EUR
assert!(rate.value() > &rust_decimal::Decimal::ZERO);
// Invalid rates return an error
assert!(Rate::<USD, EUR>::try_new(0.0).is_err());
assert!(Rate::<USD, EUR>::try_new(-1.0).is_err());Examples found in repository?
11fn main() {
12 println!("=== Error Handling Examples ===\n");
13
14 // ========================================
15 // Parse Errors
16 // ========================================
17 println!("1. PARSING ERRORS");
18 println!("-----------------");
19
20 // Valid parsing
21 match Amount::<USD>::from_str("123.45") {
22 Ok(amount) => println!("✓ Parsed: {}", amount),
23 Err(e) => println!("✗ Error: {}", e),
24 }
25
26 // Invalid formats
27 let invalid_inputs = vec!["invalid", "12.34.56", "abc123", "", " "];
28
29 println!("\nInvalid inputs:");
30 for input in invalid_inputs {
31 match Amount::<USD>::from_str(input) {
32 Ok(amount) => println!(" '{}' → {}", input, amount),
33 Err(MoneyError::ParseError { input: inp, .. }) => {
34 println!(" '{}' → Parse error (input: '{}')", input, inp);
35 }
36 Err(e) => println!(" '{}' → Error: {}", input, e),
37 }
38 }
39
40 // ========================================
41 // Precision Errors
42 // ========================================
43 println!("\n2. PRECISION ERRORS");
44 println!("-------------------");
45
46 // Division creates excess precision
47 let amount = Amount::<USD>::from_major(10) / 3; // $3.333...
48 println!("After division: {}", amount);
49 println!("Decimal places: {}", amount.precision());
50 println!("Currency expects: {}", Amount::<USD>::currency_precision());
51
52 // Check for precision issues
53 match amount.check_precision() {
54 Ok(()) => println!("✓ Precision OK"),
55 Err(MoneyError::PrecisionError {
56 expected,
57 actual,
58 suggestion,
59 ..
60 }) => {
61 println!("✗ Precision error:");
62 println!(" Expected: {} decimals", expected);
63 println!(" Actual: {} decimals", actual);
64 println!(" Suggestion: {}", suggestion);
65
66 // Recover by normalizing
67 let normalized = amount.normalize();
68 println!("\n✓ After normalizing: {}", normalized);
69 println!(" Precision OK: {}", normalized.check_precision().is_ok());
70 }
71 Err(e) => println!("✗ Unexpected error: {}", e),
72 }
73
74 // ========================================
75 // Invalid Rate Errors
76 // ========================================
77 println!("\n3. INVALID RATE ERRORS");
78 println!("----------------------");
79
80 // Valid rate
81 match Rate::<USD, EUR>::try_new(0.85) {
82 Ok(rate) => println!("✓ Valid rate: {}", rate.value()),
83 Err(e) => println!("✗ Error: {}", e),
84 }
85
86 // Invalid rates
87 let invalid_rates = vec![
88 ("negative", -1.0),
89 ("zero", 0.0),
90 ("NaN", f64::NAN),
91 ("infinity", f64::INFINITY),
92 ];
93
94 println!("\nInvalid rates:");
95 for (desc, value) in invalid_rates {
96 match Rate::<USD, EUR>::try_new(value) {
97 Ok(rate) => println!(
98 " {} ({}) → Unexpected success: {}",
99 desc,
100 value,
101 rate.value()
102 ),
103 Err(MoneyError::InvalidRate { reason, .. }) => {
104 println!(" {} ({}) → {}", desc, value, reason);
105 }
106 Err(e) => println!(" {} ({}) → Error: {}", desc, value, e),
107 }
108 }
109
110 // ========================================
111 // Error Suggestions
112 // ========================================
113 println!("\n4. ERROR RECOVERY SUGGESTIONS");
114 println!("------------------------------");
115
116 let errors = vec![
117 MoneyError::PrecisionError {
118 currency: "USD",
119 expected: 2,
120 actual: 5,
121 suggestion: "Use normalize() or round() to adjust precision".to_string(),
122 },
123 MoneyError::InvalidRate {
124 value: "-1.0".to_string(),
125 reason: "Rate must be positive".to_string(),
126 },
127 MoneyError::ParseError {
128 input: "abc".to_string(),
129 expected_currency: Some("USD"),
130 reason: "Invalid number format".to_string(),
131 },
132 ];
133
134 for error in errors {
135 println!("\nError: {}", error);
136 println!("Suggestion: {}", error.suggestion());
137 if let Some(currency) = error.currency() {
138 println!("Currency: {}", currency);
139 }
140 }
141
142 // ========================================
143 // Safe Division
144 // ========================================
145 println!("\n5. SAFE DIVISION");
146 println!("----------------");
147
148 let amount = Amount::<USD>::from_major(100);
149
150 // Division by zero is handled
151 let divisor = 0;
152 println!("Dividing {} by {}...", amount, divisor);
153
154 if divisor == 0 {
155 println!("✗ Cannot divide by zero!");
156 println!(" Handled before attempting division");
157 } else {
158 let result = amount / divisor;
159 println!("✓ Result: {}", result);
160 }
161
162 // Safe division with non-zero
163 let safe_divisor = 3;
164 let result = amount / safe_divisor;
165 println!("\nDividing {} by {}: {}", amount, safe_divisor, result);
166
167 // ========================================
168 // Pattern Matching on Errors
169 // ========================================
170 println!("\n6. PATTERN MATCHING");
171 println!("-------------------");
172
173 fn parse_and_handle(input: &str) -> MoneyResult<Amount<USD>> {
174 Amount::<USD>::from_str(input)
175 }
176
177 let inputs = vec!["123.45", "invalid", "999.99"];
178
179 for input in inputs {
180 print!("Parsing '{}': ", input);
181
182 match parse_and_handle(input) {
183 Ok(amount) => {
184 println!("✓ Success: {}", amount);
185 }
186 Err(MoneyError::ParseError { input, reason, .. }) => {
187 println!("✗ Parse error");
188 println!(" Input: '{}'", input);
189 println!(" Reason: {}", reason);
190 }
191 Err(e) => {
192 println!("✗ Other error: {}", e);
193 }
194 }
195 }
196
197 // ========================================
198 // Error Propagation with ?
199 // ========================================
200 println!("\n7. ERROR PROPAGATION");
201 println!("--------------------");
202
203 fn calculate_total(price_str: &str, quantity: i64) -> MoneyResult<Amount<USD>> {
204 let price = Amount::<USD>::from_str(price_str)?;
205 let total = price * quantity;
206 total.check_precision()?;
207 Ok(total)
208 }
209
210 match calculate_total("29.99", 3) {
211 Ok(total) => println!("✓ Total: {}", total),
212 Err(e) => println!("✗ Error: {}", e),
213 }
214
215 match calculate_total("invalid", 3) {
216 Ok(total) => println!("✓ Total: {}", total),
217 Err(e) => println!("✗ Error: {}", e),
218 }
219
220 // ========================================
221 // Recovering from Errors
222 // ========================================
223 println!("\n8. ERROR RECOVERY");
224 println!("-----------------");
225
226 fn parse_with_fallback(input: &str, fallback: Amount<USD>) -> Amount<USD> {
227 Amount::<USD>::from_str(input).unwrap_or(fallback)
228 }
229
230 let fallback = Amount::<USD>::from_major(0);
231
232 let inputs = vec!["123.45", "invalid", "67.89"];
233 for input in inputs {
234 let amount = parse_with_fallback(input, fallback);
235 println!("'{}' → {}", input, amount);
236 }
237
238 // ========================================
239 // Validation Before Operations
240 // ========================================
241 println!("\n9. VALIDATION");
242 println!("-------------");
243
244 fn safe_divide(amount: Amount<USD>, divisor: i64) -> MoneyResult<Amount<USD>> {
245 if divisor == 0 {
246 return Err(MoneyError::InvalidAmount {
247 currency: Some("USD"),
248 reason: "Cannot divide by zero".to_string(),
249 });
250 }
251
252 let result = amount / divisor;
253
254 // Check precision after division
255 result.check_precision()?;
256
257 Ok(result)
258 }
259
260 let amount = Amount::<USD>::from_major(100);
261
262 match safe_divide(amount, 0) {
263 Ok(result) => println!(" Division by 0: {}", result),
264 Err(e) => println!(" Division by 0: Error - {}", e),
265 }
266
267 match safe_divide(amount, 3) {
268 Ok(result) => println!(" Division by 3: {}", result),
269 Err(e) => println!(" Division by 3: Error - {}", e),
270 }
271
272 // ========================================
273 // Real-World: Parsing User Input
274 // ========================================
275 println!("\n10. REAL-WORLD: PARSING USER INPUT");
276 println!("-----------------------------------");
277
278 fn process_payment(amount_str: &str) -> MoneyResult<String> {
279 // Parse the amount
280 let amount = Amount::<USD>::from_str(amount_str)?;
281
282 // Validate it's positive
283 if amount.to_minor() <= 0 {
284 return Err(MoneyError::InvalidAmount {
285 currency: Some("USD"),
286 reason: "Payment amount must be positive".to_string(),
287 });
288 }
289
290 // Process the payment
291 let fee = (amount * 3) / 100; // 3% fee
292 let total = amount + fee;
293
294 Ok(format!(
295 "Payment: {}, Fee: {}, Total: {}",
296 amount, fee, total
297 ))
298 }
299
300 let test_inputs = vec!["100.00", "0", "-50", "abc", "250.50"];
301
302 for input in test_inputs {
303 println!("\nProcessing payment: '{}'", input);
304 match process_payment(input) {
305 Ok(summary) => println!(" ✓ {}", summary),
306 Err(e) => {
307 println!(" ✗ Error: {}", e);
308 let suggestion = e.suggestion();
309 println!(" Hint: {}", suggestion);
310 }
311 }
312 }
313
314 // ========================================
315 // Rounding to Fix Precision
316 // ========================================
317 println!("\n11. FIXING PRECISION WITH ROUNDING");
318 println!("-----------------------------------");
319
320 let amount = Amount::<USD>::from_major(10) / 3; // Creates excess precision
321
322 println!("Original: {}", amount);
323 println!(
324 "Precision check: {}",
325 if amount.check_precision().is_ok() {
326 "✓ OK"
327 } else {
328 "✗ Excess precision"
329 }
330 );
331
332 // Fix with rounding
333 let rounded = amount.round(RoundingMode::HalfUp);
334 println!("\nRounded: {}", rounded);
335 println!(
336 "Precision check: {}",
337 if rounded.check_precision().is_ok() {
338 "✓ OK"
339 } else {
340 "✗ Excess precision"
341 }
342 );
343
344 // Or normalize (uses banker's rounding)
345 let normalized = amount.normalize();
346 println!("\nNormalized: {}", normalized);
347 println!(
348 "Precision check: {}",
349 if normalized.check_precision().is_ok() {
350 "✓ OK"
351 } else {
352 "✗ Excess precision"
353 }
354 );
355
356 println!("\n=== All error handling examples completed! ===");
357}Sourcepub fn new(rate: f64) -> Self
pub fn new(rate: f64) -> Self
Creates a new exchange rate from a floating-point value.
§Panics
Panics if the rate is zero, negative, NaN, or infinite.
For a non-panicking version, use try_new.
§Examples
use typed_money::{Rate, USD, EUR};
let rate = Rate::<USD, EUR>::new(0.85); // 1 USD = 0.85 EUR§Panics Examples
use typed_money::{Rate, USD, EUR};
let rate = Rate::<USD, EUR>::new(0.0); // Panics: rate must be positiveExamples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}More examples
51fn main() {
52 println!("=== Typed Money - Global Currencies Example ===\n");
53
54 // 1. MAJOR FIAT CURRENCIES
55 println!("1. MAJOR FIAT CURRENCIES");
56 println!("------------------------");
57 let usd = Amount::<USD>::from_major(100);
58 let cad = Amount::<CAD>::from_major(135);
59 let chf = Amount::<CHF>::from_major(90);
60 let aud = Amount::<AUD>::from_major(150);
61 let nzd = Amount::<NZD>::from_major(160);
62
63 println!("USD: {} ({} decimals)", usd, USD::DECIMALS);
64 println!("CAD: {} ({} decimals)", cad, CAD::DECIMALS);
65 println!("CHF: {} ({} decimals)", chf, CHF::DECIMALS);
66 println!("AUD: {} ({} decimals)", aud, AUD::DECIMALS);
67 println!("NZD: {} ({} decimals)", nzd, NZD::DECIMALS);
68 println!();
69
70 // 2. ASIAN CURRENCIES
71 println!("2. ASIAN CURRENCIES");
72 println!("-------------------");
73 let cny = Amount::<CNY>::from_major(720);
74 let krw = Amount::<KRW>::from_major(130_000);
75 let sgd = Amount::<SGD>::from_major(135);
76 let hkd = Amount::<HKD>::from_major(780);
77 let twd = Amount::<TWD>::from_major(3100);
78 let inr = Amount::<INR>::from_major(8300);
79
80 println!("CNY: {} ({} decimals)", cny, CNY::DECIMALS);
81 println!("KRW: {} ({} decimals)", krw, KRW::DECIMALS);
82 println!("SGD: {} ({} decimals)", sgd, SGD::DECIMALS);
83 println!("HKD: {} ({} decimals)", hkd, HKD::DECIMALS);
84 println!("TWD: {} ({} decimals)", twd, TWD::DECIMALS);
85 println!("INR: {} ({} decimals)", inr, INR::DECIMALS);
86 println!();
87
88 // 3. EUROPEAN CURRENCIES
89 println!("3. EUROPEAN CURRENCIES");
90 println!("----------------------");
91 let eur = Amount::<EUR>::from_major(85);
92 let gbp = Amount::<GBP>::from_major(75);
93 let sek = Amount::<SEK>::from_major(1050);
94 let nok = Amount::<NOK>::from_major(1100);
95 let dkk = Amount::<DKK>::from_major(650);
96 let pln = Amount::<PLN>::from_major(400);
97 let czk = Amount::<CZK>::from_major(2300);
98 let huf = Amount::<HUF>::from_major(36_000);
99
100 println!("EUR: {} ({} decimals)", eur, EUR::DECIMALS);
101 println!("GBP: {} ({} decimals)", gbp, GBP::DECIMALS);
102 println!("SEK: {} ({} decimals)", sek, SEK::DECIMALS);
103 println!("NOK: {} ({} decimals)", nok, NOK::DECIMALS);
104 println!("DKK: {} ({} decimals)", dkk, DKK::DECIMALS);
105 println!("PLN: {} ({} decimals)", pln, PLN::DECIMALS);
106 println!("CZK: {} ({} decimals)", czk, CZK::DECIMALS);
107 println!("HUF: {} ({} decimals)", huf, HUF::DECIMALS);
108 println!();
109
110 // 4. AMERICAN CURRENCIES
111 println!("4. AMERICAN CURRENCIES");
112 println!("----------------------");
113 let brl = Amount::<BRL>::from_major(500);
114 let mxn = Amount::<MXN>::from_major(1700);
115 let ars = Amount::<ARS>::from_major(85_000);
116 let clp = Amount::<CLP>::from_major(90_000);
117
118 println!("BRL: {} ({} decimals)", brl, BRL::DECIMALS);
119 println!("MXN: {} ({} decimals)", mxn, MXN::DECIMALS);
120 println!("ARS: {} ({} decimals)", ars, ARS::DECIMALS);
121 println!("CLP: {} ({} decimals)", clp, CLP::DECIMALS);
122 println!();
123
124 // 5. AFRICAN/MIDDLE EASTERN CURRENCIES
125 println!("5. AFRICAN/MIDDLE EASTERN CURRENCIES");
126 println!("------------------------------------");
127 let zar = Amount::<ZAR>::from_major(1800);
128 let egp = Amount::<EGP>::from_major(3100);
129 let aed = Amount::<AED>::from_major(370);
130 let sar = Amount::<SAR>::from_major(375);
131 let ils = Amount::<ILS>::from_major(360);
132 let try_currency = Amount::<TRY>::from_major(3000);
133
134 println!("ZAR: {} ({} decimals)", zar, ZAR::DECIMALS);
135 println!("EGP: {} ({} decimals)", egp, EGP::DECIMALS);
136 println!("AED: {} ({} decimals)", aed, AED::DECIMALS);
137 println!("SAR: {} ({} decimals)", sar, SAR::DECIMALS);
138 println!("ILS: {} ({} decimals)", ils, ILS::DECIMALS);
139 println!("TRY: {} ({} decimals)", try_currency, TRY::DECIMALS);
140 println!();
141
142 // 6. CRYPTOCURRENCIES
143 println!("6. CRYPTOCURRENCIES");
144 println!("-------------------");
145 let btc = Amount::<BTC>::from_minor(100_000_000); // 1.00000000 BTC
146 let eth = Amount::<ETH>::from_minor(1_000_000_000_000_000_000); // 1.000000000000000000 ETH
147
148 println!("BTC: {} ({} decimals)", btc, BTC::DECIMALS);
149 println!("ETH: {} ({} decimals)", eth, ETH::DECIMALS);
150 println!();
151
152 // 7. CURRENCY CONVERSION EXAMPLES
153 println!("7. CURRENCY CONVERSION EXAMPLES");
154 println!("-------------------------------");
155
156 // USD to EUR
157 let usd_to_eur = Rate::<USD, EUR>::new(0.85)
158 .with_timestamp_unix_secs(1_700_000_000)
159 .with_source("ECB");
160 let eur_converted = usd.convert(&usd_to_eur);
161 println!(
162 "USD to EUR: {} → {} (rate: {})",
163 usd,
164 eur_converted,
165 usd_to_eur.value()
166 );
167
168 // EUR to GBP
169 let eur_to_gbp = Rate::<EUR, GBP>::new(0.87);
170 let gbp_converted = eur_converted.convert(&eur_to_gbp);
171 println!(
172 "EUR to GBP: {} → {} (rate: {})",
173 eur_converted,
174 gbp_converted,
175 eur_to_gbp.value()
176 );
177
178 // USD to JPY
179 let usd_to_jpy = Rate::<USD, JPY>::new(150.0);
180 let jpy_converted = usd.convert(&usd_to_jpy);
181 println!(
182 "USD to JPY: {} → {} (rate: {})",
183 usd,
184 jpy_converted,
185 usd_to_jpy.value()
186 );
187 println!();
188
189 // 8. ROUNDING EXAMPLES
190 println!("8. ROUNDING EXAMPLES");
191 println!("--------------------");
192 let usd_amount = Amount::<USD>::from_minor(12345); // $123.45
193 println!("Original: {}", usd_amount);
194 println!("Half Up: {}", usd_amount.round(RoundingMode::HalfUp));
195 println!("Half Down: {}", usd_amount.round(RoundingMode::HalfDown));
196 println!("Half Even: {}", usd_amount.round(RoundingMode::HalfEven));
197 println!("Floor: {}", usd_amount.round(RoundingMode::Floor));
198 println!("Ceiling: {}", usd_amount.round(RoundingMode::Ceiling));
199 println!();
200
201 // 9. CURRENCY METADATA
202 println!("9. CURRENCY METADATA");
203 println!("--------------------");
204 let currencies = [
205 ("USD", USD::CODE, USD::SYMBOL, USD::DECIMALS),
206 ("EUR", EUR::CODE, EUR::SYMBOL, EUR::DECIMALS),
207 ("JPY", JPY::CODE, JPY::SYMBOL, JPY::DECIMALS),
208 ("CNY", CNY::CODE, CNY::SYMBOL, CNY::DECIMALS),
209 ("BRL", BRL::CODE, BRL::SYMBOL, BRL::DECIMALS),
210 ("AED", AED::CODE, AED::SYMBOL, AED::DECIMALS),
211 ];
212
213 for (name, code, symbol, decimals) in currencies {
214 println!("{}: {} {} ({} decimals)", name, symbol, code, decimals);
215 }
216 println!();
217
218 // 10. TYPE SAFETY DEMONSTRATION
219 println!("10. TYPE SAFETY DEMONSTRATION");
220 println!("-----------------------------");
221 println!("✓ USD + USD = Valid");
222 println!("✓ EUR + EUR = Valid");
223 println!("✓ CAD + CAD = Valid");
224 println!("✗ USD + EUR = Compile Error!");
225 println!("✗ CAD + JPY = Compile Error!");
226 println!("✗ BRL + TRY = Compile Error!");
227 println!();
228
229 println!("=== Global Currencies Example Completed! ===");
230 println!("Total currencies supported: 30+");
231 println!("Regions covered: North America, Europe, Asia, South America, Africa, Middle East");
232 println!("Type safety: 100% compile-time currency mixing prevention");
233}99fn main() {
100 println!("=== Custom Currency Examples ===\n");
101
102 // ========================================
103 // Using Custom Fiat Currencies
104 // ========================================
105 println!("1. CUSTOM FIAT CURRENCIES");
106 println!("-------------------------");
107
108 let cad = Amount::<CAD>::from_major(100);
109 let chf = Amount::<CHF>::from_major(85);
110 let aud = Amount::<AUD>::from_major(150);
111
112 println!("Canadian Dollar: {}", cad);
113 println!("Swiss Franc: {}", chf);
114 println!("Australian Dollar: {}", aud);
115
116 // Arithmetic works the same
117 let total_cad = cad + Amount::<CAD>::from_major(50);
118 println!("\nC$100 + C$50 = {}", total_cad);
119
120 // ========================================
121 // Currency Properties
122 // ========================================
123 println!("\n2. CURRENCY PROPERTIES");
124 println!("----------------------");
125
126 println!(
127 "CAD: code={}, symbol={}, decimals={}",
128 CAD::CODE,
129 CAD::SYMBOL,
130 CAD::DECIMALS
131 );
132 println!(
133 "CHF: code={}, symbol={}, decimals={}",
134 CHF::CODE,
135 CHF::SYMBOL,
136 CHF::DECIMALS
137 );
138 println!(
139 "DOGE: code={}, symbol={}, decimals={}",
140 DOGE::CODE,
141 DOGE::SYMBOL,
142 DOGE::DECIMALS
143 );
144 println!(
145 "GOLD: code={}, symbol={}, decimals={}",
146 GOLD::CODE,
147 GOLD::SYMBOL,
148 GOLD::DECIMALS
149 );
150
151 // ========================================
152 // Converting Between Custom Currencies
153 // ========================================
154 println!("\n3. CONVERTING CUSTOM CURRENCIES");
155 println!("--------------------------------");
156
157 let _cad_amount = Amount::<CAD>::from_major(100);
158 let cad_to_aud = Rate::<CAD, AUD>::new(1.08); // 1 CAD = 1.08 AUD
159
160 println!("Example: C$100 at rate {} CAD→AUD", cad_to_aud.value());
161
162 // ========================================
163 // Cryptocurrency Example
164 // ========================================
165 println!("\n4. CRYPTOCURRENCY (DOGECOIN)");
166 println!("-----------------------------");
167
168 // Dogecoin with 8 decimal places (like Bitcoin)
169 let doge = Amount::<DOGE>::from_minor(100_000_000); // 1 DOGE
170 println!("Amount: {} (1 DOGE)", doge);
171
172 let small_amount = Amount::<DOGE>::from_minor(12_345_678); // 0.12345678 DOGE
173 println!("Small amount: {} (0.12345678 DOGE)", small_amount);
174
175 let total = doge + small_amount;
176 println!("Total: {}", total);
177
178 // ========================================
179 // Video Game Currency
180 // ========================================
181 println!("\n5. VIDEO GAME CURRENCIES");
182 println!("------------------------");
183
184 // Gold coins (no fractional amounts)
185 let gold = Amount::<GOLD>::from_major(1000);
186 println!("Gold coins: {}", gold);
187
188 let loot = Amount::<GOLD>::from_major(150);
189 let total_gold = gold + loot;
190 println!(
191 "After looting: {} (was {}, found {})",
192 total_gold, gold, loot
193 );
194
195 // Premium gems (with fractional amounts for bonuses)
196 let gems = Amount::<GEMS>::from_major(50);
197 println!("\nPremium gems: {}", gems);
198
199 // 10% bonus
200 let bonus = (gems * 10) / 100;
201 println!("Bonus (10%): {}", bonus);
202
203 let total_gems = gems + bonus;
204 println!("Total with bonus: {}", total_gems);
205
206 // ========================================
207 // Loyalty Points System
208 // ========================================
209 println!("\n6. LOYALTY POINTS SYSTEM");
210 println!("------------------------");
211
212 let purchase = Amount::<POINTS>::from_major(100);
213 println!("Purchase: {}", purchase);
214
215 // Earn 5% back in points
216 let earn_rate = 5;
217 let points_earned = (purchase * earn_rate) / 100;
218 println!("Points earned ({}%): {}", earn_rate, points_earned);
219
220 // Accumulate points
221 let existing_points = Amount::<POINTS>::from_major(237);
222 let new_balance = existing_points + points_earned;
223 println!("\nPrevious balance: {}", existing_points);
224 println!("New balance: {}", new_balance);
225
226 // Redeem points
227 let redemption = Amount::<POINTS>::from_major(50);
228 let final_balance = new_balance - redemption;
229 println!("\nAfter redeeming {}: {}", redemption, final_balance);
230
231 // ========================================
232 // Exchange Rate Between Custom Currencies
233 // ========================================
234 println!("\n7. EXCHANGE RATES BETWEEN CUSTOM CURRENCIES");
235 println!("--------------------------------------------");
236
237 // Define exchange rates
238 let cad_to_aud = Rate::<CAD, AUD>::new(1.08); // 1 CAD = 1.08 AUD
239
240 let cad_amount = Amount::<CAD>::from_major(100);
241 println!("Canadian Dollars: {}", cad_amount);
242 println!("Exchange rate: 1 CAD = {} AUD", cad_to_aud.value());
243
244 let aud_amount = cad_amount.convert(&cad_to_aud);
245 println!("Australian Dollars: {}", aud_amount);
246
247 // ========================================
248 // Type Safety Still Works
249 // ========================================
250 println!("\n8. TYPE SAFETY");
251 println!("--------------");
252
253 println!("✓ Can add CAD + CAD");
254 println!("✓ Can add GOLD + GOLD");
255 println!("✗ Cannot add CAD + CHF (compile error!)");
256 println!("✗ Cannot add GOLD + GEMS (compile error!)");
257 println!("\nCustom currencies have the same type safety as built-in ones!");
258
259 // These would NOT compile:
260 // let invalid = cad + chf; // Compile error: different currencies
261 // let invalid2 = gold + gems; // Compile error: different currencies
262
263 // ========================================
264 // Rounding with Custom Currencies
265 // ========================================
266 println!("\n9. ROUNDING");
267 println!("-----------");
268
269 let cad = Amount::<CAD>::from_major(100) / 3; // C$33.333...
270 println!("CAD (exact): {}", cad);
271 println!("CAD (rounded): {}", cad.round(RoundingMode::HalfUp));
272
273 let doge = Amount::<DOGE>::from_minor(100_000_000) / 3; // 0.33333333 DOGE
274 println!("\nDOGE (exact): {}", doge);
275 println!("DOGE (rounded): {}", doge.round(RoundingMode::HalfUp));
276
277 let gold = Amount::<GOLD>::from_major(1000) / 3; // 333.333... coins
278 println!("\nGOLD (exact): {}", gold);
279 println!(
280 "GOLD (rounded): {} (no decimals)",
281 gold.round(RoundingMode::HalfUp)
282 );
283
284 // ========================================
285 // Real-World: Multi-Currency Wallet
286 // ========================================
287 println!("\n10. REAL-WORLD: MULTI-CURRENCY WALLET");
288 println!("--------------------------------------");
289
290 println!("Wallet balances:");
291 let cad_balance = Amount::<CAD>::from_major(500);
292 let aud_balance = Amount::<AUD>::from_major(300);
293 let chf_balance = Amount::<CHF>::from_major(200);
294
295 println!(" CAD: {}", cad_balance);
296 println!(" AUD: {}", aud_balance);
297 println!(" CHF: {}", chf_balance);
298
299 println!("\nTransaction: Spend C$50");
300 let new_cad = cad_balance - Amount::<CAD>::from_major(50);
301 println!(" New CAD balance: {}", new_cad);
302
303 println!("\nType system ensures you can't accidentally mix currencies!");
304
305 println!("\n=== All custom currency examples completed! ===");
306}Sourcepub fn try_from_decimal(rate: Decimal) -> MoneyResult<Self>
pub fn try_from_decimal(rate: Decimal) -> MoneyResult<Self>
Tries to create a new exchange rate from a Decimal value.
This is useful when you already have a precise decimal rate. Returns an error if the rate is zero or negative.
§Examples
use typed_money::{Rate, USD, EUR};
use rust_decimal::Decimal;
let decimal_rate = Decimal::new(85, 2); // 0.85
let rate = Rate::<USD, EUR>::try_from_decimal(decimal_rate)?;
// Invalid rates return an error
assert!(Rate::<USD, EUR>::try_from_decimal(Decimal::ZERO).is_err());Sourcepub fn from_decimal(rate: Decimal) -> Self
pub fn from_decimal(rate: Decimal) -> Self
Creates a new exchange rate from a Decimal value.
§Panics
Panics if the rate is zero or negative.
For a non-panicking version, use try_from_decimal.
§Examples
use typed_money::{Rate, USD, EUR};
use rust_decimal::Decimal;
let decimal_rate = Decimal::new(85, 2); // 0.85
let rate = Rate::<USD, EUR>::from_decimal(decimal_rate);Sourcepub const fn value(&self) -> &Decimal
pub const fn value(&self) -> &Decimal
Returns the exchange rate value.
§Examples
use typed_money::{Rate, USD, EUR};
let rate = Rate::<USD, EUR>::new(0.85);
println!("Rate: {}", rate.value());Examples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}More examples
51fn main() {
52 println!("=== Typed Money - Global Currencies Example ===\n");
53
54 // 1. MAJOR FIAT CURRENCIES
55 println!("1. MAJOR FIAT CURRENCIES");
56 println!("------------------------");
57 let usd = Amount::<USD>::from_major(100);
58 let cad = Amount::<CAD>::from_major(135);
59 let chf = Amount::<CHF>::from_major(90);
60 let aud = Amount::<AUD>::from_major(150);
61 let nzd = Amount::<NZD>::from_major(160);
62
63 println!("USD: {} ({} decimals)", usd, USD::DECIMALS);
64 println!("CAD: {} ({} decimals)", cad, CAD::DECIMALS);
65 println!("CHF: {} ({} decimals)", chf, CHF::DECIMALS);
66 println!("AUD: {} ({} decimals)", aud, AUD::DECIMALS);
67 println!("NZD: {} ({} decimals)", nzd, NZD::DECIMALS);
68 println!();
69
70 // 2. ASIAN CURRENCIES
71 println!("2. ASIAN CURRENCIES");
72 println!("-------------------");
73 let cny = Amount::<CNY>::from_major(720);
74 let krw = Amount::<KRW>::from_major(130_000);
75 let sgd = Amount::<SGD>::from_major(135);
76 let hkd = Amount::<HKD>::from_major(780);
77 let twd = Amount::<TWD>::from_major(3100);
78 let inr = Amount::<INR>::from_major(8300);
79
80 println!("CNY: {} ({} decimals)", cny, CNY::DECIMALS);
81 println!("KRW: {} ({} decimals)", krw, KRW::DECIMALS);
82 println!("SGD: {} ({} decimals)", sgd, SGD::DECIMALS);
83 println!("HKD: {} ({} decimals)", hkd, HKD::DECIMALS);
84 println!("TWD: {} ({} decimals)", twd, TWD::DECIMALS);
85 println!("INR: {} ({} decimals)", inr, INR::DECIMALS);
86 println!();
87
88 // 3. EUROPEAN CURRENCIES
89 println!("3. EUROPEAN CURRENCIES");
90 println!("----------------------");
91 let eur = Amount::<EUR>::from_major(85);
92 let gbp = Amount::<GBP>::from_major(75);
93 let sek = Amount::<SEK>::from_major(1050);
94 let nok = Amount::<NOK>::from_major(1100);
95 let dkk = Amount::<DKK>::from_major(650);
96 let pln = Amount::<PLN>::from_major(400);
97 let czk = Amount::<CZK>::from_major(2300);
98 let huf = Amount::<HUF>::from_major(36_000);
99
100 println!("EUR: {} ({} decimals)", eur, EUR::DECIMALS);
101 println!("GBP: {} ({} decimals)", gbp, GBP::DECIMALS);
102 println!("SEK: {} ({} decimals)", sek, SEK::DECIMALS);
103 println!("NOK: {} ({} decimals)", nok, NOK::DECIMALS);
104 println!("DKK: {} ({} decimals)", dkk, DKK::DECIMALS);
105 println!("PLN: {} ({} decimals)", pln, PLN::DECIMALS);
106 println!("CZK: {} ({} decimals)", czk, CZK::DECIMALS);
107 println!("HUF: {} ({} decimals)", huf, HUF::DECIMALS);
108 println!();
109
110 // 4. AMERICAN CURRENCIES
111 println!("4. AMERICAN CURRENCIES");
112 println!("----------------------");
113 let brl = Amount::<BRL>::from_major(500);
114 let mxn = Amount::<MXN>::from_major(1700);
115 let ars = Amount::<ARS>::from_major(85_000);
116 let clp = Amount::<CLP>::from_major(90_000);
117
118 println!("BRL: {} ({} decimals)", brl, BRL::DECIMALS);
119 println!("MXN: {} ({} decimals)", mxn, MXN::DECIMALS);
120 println!("ARS: {} ({} decimals)", ars, ARS::DECIMALS);
121 println!("CLP: {} ({} decimals)", clp, CLP::DECIMALS);
122 println!();
123
124 // 5. AFRICAN/MIDDLE EASTERN CURRENCIES
125 println!("5. AFRICAN/MIDDLE EASTERN CURRENCIES");
126 println!("------------------------------------");
127 let zar = Amount::<ZAR>::from_major(1800);
128 let egp = Amount::<EGP>::from_major(3100);
129 let aed = Amount::<AED>::from_major(370);
130 let sar = Amount::<SAR>::from_major(375);
131 let ils = Amount::<ILS>::from_major(360);
132 let try_currency = Amount::<TRY>::from_major(3000);
133
134 println!("ZAR: {} ({} decimals)", zar, ZAR::DECIMALS);
135 println!("EGP: {} ({} decimals)", egp, EGP::DECIMALS);
136 println!("AED: {} ({} decimals)", aed, AED::DECIMALS);
137 println!("SAR: {} ({} decimals)", sar, SAR::DECIMALS);
138 println!("ILS: {} ({} decimals)", ils, ILS::DECIMALS);
139 println!("TRY: {} ({} decimals)", try_currency, TRY::DECIMALS);
140 println!();
141
142 // 6. CRYPTOCURRENCIES
143 println!("6. CRYPTOCURRENCIES");
144 println!("-------------------");
145 let btc = Amount::<BTC>::from_minor(100_000_000); // 1.00000000 BTC
146 let eth = Amount::<ETH>::from_minor(1_000_000_000_000_000_000); // 1.000000000000000000 ETH
147
148 println!("BTC: {} ({} decimals)", btc, BTC::DECIMALS);
149 println!("ETH: {} ({} decimals)", eth, ETH::DECIMALS);
150 println!();
151
152 // 7. CURRENCY CONVERSION EXAMPLES
153 println!("7. CURRENCY CONVERSION EXAMPLES");
154 println!("-------------------------------");
155
156 // USD to EUR
157 let usd_to_eur = Rate::<USD, EUR>::new(0.85)
158 .with_timestamp_unix_secs(1_700_000_000)
159 .with_source("ECB");
160 let eur_converted = usd.convert(&usd_to_eur);
161 println!(
162 "USD to EUR: {} → {} (rate: {})",
163 usd,
164 eur_converted,
165 usd_to_eur.value()
166 );
167
168 // EUR to GBP
169 let eur_to_gbp = Rate::<EUR, GBP>::new(0.87);
170 let gbp_converted = eur_converted.convert(&eur_to_gbp);
171 println!(
172 "EUR to GBP: {} → {} (rate: {})",
173 eur_converted,
174 gbp_converted,
175 eur_to_gbp.value()
176 );
177
178 // USD to JPY
179 let usd_to_jpy = Rate::<USD, JPY>::new(150.0);
180 let jpy_converted = usd.convert(&usd_to_jpy);
181 println!(
182 "USD to JPY: {} → {} (rate: {})",
183 usd,
184 jpy_converted,
185 usd_to_jpy.value()
186 );
187 println!();
188
189 // 8. ROUNDING EXAMPLES
190 println!("8. ROUNDING EXAMPLES");
191 println!("--------------------");
192 let usd_amount = Amount::<USD>::from_minor(12345); // $123.45
193 println!("Original: {}", usd_amount);
194 println!("Half Up: {}", usd_amount.round(RoundingMode::HalfUp));
195 println!("Half Down: {}", usd_amount.round(RoundingMode::HalfDown));
196 println!("Half Even: {}", usd_amount.round(RoundingMode::HalfEven));
197 println!("Floor: {}", usd_amount.round(RoundingMode::Floor));
198 println!("Ceiling: {}", usd_amount.round(RoundingMode::Ceiling));
199 println!();
200
201 // 9. CURRENCY METADATA
202 println!("9. CURRENCY METADATA");
203 println!("--------------------");
204 let currencies = [
205 ("USD", USD::CODE, USD::SYMBOL, USD::DECIMALS),
206 ("EUR", EUR::CODE, EUR::SYMBOL, EUR::DECIMALS),
207 ("JPY", JPY::CODE, JPY::SYMBOL, JPY::DECIMALS),
208 ("CNY", CNY::CODE, CNY::SYMBOL, CNY::DECIMALS),
209 ("BRL", BRL::CODE, BRL::SYMBOL, BRL::DECIMALS),
210 ("AED", AED::CODE, AED::SYMBOL, AED::DECIMALS),
211 ];
212
213 for (name, code, symbol, decimals) in currencies {
214 println!("{}: {} {} ({} decimals)", name, symbol, code, decimals);
215 }
216 println!();
217
218 // 10. TYPE SAFETY DEMONSTRATION
219 println!("10. TYPE SAFETY DEMONSTRATION");
220 println!("-----------------------------");
221 println!("✓ USD + USD = Valid");
222 println!("✓ EUR + EUR = Valid");
223 println!("✓ CAD + CAD = Valid");
224 println!("✗ USD + EUR = Compile Error!");
225 println!("✗ CAD + JPY = Compile Error!");
226 println!("✗ BRL + TRY = Compile Error!");
227 println!();
228
229 println!("=== Global Currencies Example Completed! ===");
230 println!("Total currencies supported: 30+");
231 println!("Regions covered: North America, Europe, Asia, South America, Africa, Middle East");
232 println!("Type safety: 100% compile-time currency mixing prevention");
233}99fn main() {
100 println!("=== Custom Currency Examples ===\n");
101
102 // ========================================
103 // Using Custom Fiat Currencies
104 // ========================================
105 println!("1. CUSTOM FIAT CURRENCIES");
106 println!("-------------------------");
107
108 let cad = Amount::<CAD>::from_major(100);
109 let chf = Amount::<CHF>::from_major(85);
110 let aud = Amount::<AUD>::from_major(150);
111
112 println!("Canadian Dollar: {}", cad);
113 println!("Swiss Franc: {}", chf);
114 println!("Australian Dollar: {}", aud);
115
116 // Arithmetic works the same
117 let total_cad = cad + Amount::<CAD>::from_major(50);
118 println!("\nC$100 + C$50 = {}", total_cad);
119
120 // ========================================
121 // Currency Properties
122 // ========================================
123 println!("\n2. CURRENCY PROPERTIES");
124 println!("----------------------");
125
126 println!(
127 "CAD: code={}, symbol={}, decimals={}",
128 CAD::CODE,
129 CAD::SYMBOL,
130 CAD::DECIMALS
131 );
132 println!(
133 "CHF: code={}, symbol={}, decimals={}",
134 CHF::CODE,
135 CHF::SYMBOL,
136 CHF::DECIMALS
137 );
138 println!(
139 "DOGE: code={}, symbol={}, decimals={}",
140 DOGE::CODE,
141 DOGE::SYMBOL,
142 DOGE::DECIMALS
143 );
144 println!(
145 "GOLD: code={}, symbol={}, decimals={}",
146 GOLD::CODE,
147 GOLD::SYMBOL,
148 GOLD::DECIMALS
149 );
150
151 // ========================================
152 // Converting Between Custom Currencies
153 // ========================================
154 println!("\n3. CONVERTING CUSTOM CURRENCIES");
155 println!("--------------------------------");
156
157 let _cad_amount = Amount::<CAD>::from_major(100);
158 let cad_to_aud = Rate::<CAD, AUD>::new(1.08); // 1 CAD = 1.08 AUD
159
160 println!("Example: C$100 at rate {} CAD→AUD", cad_to_aud.value());
161
162 // ========================================
163 // Cryptocurrency Example
164 // ========================================
165 println!("\n4. CRYPTOCURRENCY (DOGECOIN)");
166 println!("-----------------------------");
167
168 // Dogecoin with 8 decimal places (like Bitcoin)
169 let doge = Amount::<DOGE>::from_minor(100_000_000); // 1 DOGE
170 println!("Amount: {} (1 DOGE)", doge);
171
172 let small_amount = Amount::<DOGE>::from_minor(12_345_678); // 0.12345678 DOGE
173 println!("Small amount: {} (0.12345678 DOGE)", small_amount);
174
175 let total = doge + small_amount;
176 println!("Total: {}", total);
177
178 // ========================================
179 // Video Game Currency
180 // ========================================
181 println!("\n5. VIDEO GAME CURRENCIES");
182 println!("------------------------");
183
184 // Gold coins (no fractional amounts)
185 let gold = Amount::<GOLD>::from_major(1000);
186 println!("Gold coins: {}", gold);
187
188 let loot = Amount::<GOLD>::from_major(150);
189 let total_gold = gold + loot;
190 println!(
191 "After looting: {} (was {}, found {})",
192 total_gold, gold, loot
193 );
194
195 // Premium gems (with fractional amounts for bonuses)
196 let gems = Amount::<GEMS>::from_major(50);
197 println!("\nPremium gems: {}", gems);
198
199 // 10% bonus
200 let bonus = (gems * 10) / 100;
201 println!("Bonus (10%): {}", bonus);
202
203 let total_gems = gems + bonus;
204 println!("Total with bonus: {}", total_gems);
205
206 // ========================================
207 // Loyalty Points System
208 // ========================================
209 println!("\n6. LOYALTY POINTS SYSTEM");
210 println!("------------------------");
211
212 let purchase = Amount::<POINTS>::from_major(100);
213 println!("Purchase: {}", purchase);
214
215 // Earn 5% back in points
216 let earn_rate = 5;
217 let points_earned = (purchase * earn_rate) / 100;
218 println!("Points earned ({}%): {}", earn_rate, points_earned);
219
220 // Accumulate points
221 let existing_points = Amount::<POINTS>::from_major(237);
222 let new_balance = existing_points + points_earned;
223 println!("\nPrevious balance: {}", existing_points);
224 println!("New balance: {}", new_balance);
225
226 // Redeem points
227 let redemption = Amount::<POINTS>::from_major(50);
228 let final_balance = new_balance - redemption;
229 println!("\nAfter redeeming {}: {}", redemption, final_balance);
230
231 // ========================================
232 // Exchange Rate Between Custom Currencies
233 // ========================================
234 println!("\n7. EXCHANGE RATES BETWEEN CUSTOM CURRENCIES");
235 println!("--------------------------------------------");
236
237 // Define exchange rates
238 let cad_to_aud = Rate::<CAD, AUD>::new(1.08); // 1 CAD = 1.08 AUD
239
240 let cad_amount = Amount::<CAD>::from_major(100);
241 println!("Canadian Dollars: {}", cad_amount);
242 println!("Exchange rate: 1 CAD = {} AUD", cad_to_aud.value());
243
244 let aud_amount = cad_amount.convert(&cad_to_aud);
245 println!("Australian Dollars: {}", aud_amount);
246
247 // ========================================
248 // Type Safety Still Works
249 // ========================================
250 println!("\n8. TYPE SAFETY");
251 println!("--------------");
252
253 println!("✓ Can add CAD + CAD");
254 println!("✓ Can add GOLD + GOLD");
255 println!("✗ Cannot add CAD + CHF (compile error!)");
256 println!("✗ Cannot add GOLD + GEMS (compile error!)");
257 println!("\nCustom currencies have the same type safety as built-in ones!");
258
259 // These would NOT compile:
260 // let invalid = cad + chf; // Compile error: different currencies
261 // let invalid2 = gold + gems; // Compile error: different currencies
262
263 // ========================================
264 // Rounding with Custom Currencies
265 // ========================================
266 println!("\n9. ROUNDING");
267 println!("-----------");
268
269 let cad = Amount::<CAD>::from_major(100) / 3; // C$33.333...
270 println!("CAD (exact): {}", cad);
271 println!("CAD (rounded): {}", cad.round(RoundingMode::HalfUp));
272
273 let doge = Amount::<DOGE>::from_minor(100_000_000) / 3; // 0.33333333 DOGE
274 println!("\nDOGE (exact): {}", doge);
275 println!("DOGE (rounded): {}", doge.round(RoundingMode::HalfUp));
276
277 let gold = Amount::<GOLD>::from_major(1000) / 3; // 333.333... coins
278 println!("\nGOLD (exact): {}", gold);
279 println!(
280 "GOLD (rounded): {} (no decimals)",
281 gold.round(RoundingMode::HalfUp)
282 );
283
284 // ========================================
285 // Real-World: Multi-Currency Wallet
286 // ========================================
287 println!("\n10. REAL-WORLD: MULTI-CURRENCY WALLET");
288 println!("--------------------------------------");
289
290 println!("Wallet balances:");
291 let cad_balance = Amount::<CAD>::from_major(500);
292 let aud_balance = Amount::<AUD>::from_major(300);
293 let chf_balance = Amount::<CHF>::from_major(200);
294
295 println!(" CAD: {}", cad_balance);
296 println!(" AUD: {}", aud_balance);
297 println!(" CHF: {}", chf_balance);
298
299 println!("\nTransaction: Spend C$50");
300 let new_cad = cad_balance - Amount::<CAD>::from_major(50);
301 println!(" New CAD balance: {}", new_cad);
302
303 println!("\nType system ensures you can't accidentally mix currencies!");
304
305 println!("\n=== All custom currency examples completed! ===");
306}11fn main() {
12 println!("=== Error Handling Examples ===\n");
13
14 // ========================================
15 // Parse Errors
16 // ========================================
17 println!("1. PARSING ERRORS");
18 println!("-----------------");
19
20 // Valid parsing
21 match Amount::<USD>::from_str("123.45") {
22 Ok(amount) => println!("✓ Parsed: {}", amount),
23 Err(e) => println!("✗ Error: {}", e),
24 }
25
26 // Invalid formats
27 let invalid_inputs = vec!["invalid", "12.34.56", "abc123", "", " "];
28
29 println!("\nInvalid inputs:");
30 for input in invalid_inputs {
31 match Amount::<USD>::from_str(input) {
32 Ok(amount) => println!(" '{}' → {}", input, amount),
33 Err(MoneyError::ParseError { input: inp, .. }) => {
34 println!(" '{}' → Parse error (input: '{}')", input, inp);
35 }
36 Err(e) => println!(" '{}' → Error: {}", input, e),
37 }
38 }
39
40 // ========================================
41 // Precision Errors
42 // ========================================
43 println!("\n2. PRECISION ERRORS");
44 println!("-------------------");
45
46 // Division creates excess precision
47 let amount = Amount::<USD>::from_major(10) / 3; // $3.333...
48 println!("After division: {}", amount);
49 println!("Decimal places: {}", amount.precision());
50 println!("Currency expects: {}", Amount::<USD>::currency_precision());
51
52 // Check for precision issues
53 match amount.check_precision() {
54 Ok(()) => println!("✓ Precision OK"),
55 Err(MoneyError::PrecisionError {
56 expected,
57 actual,
58 suggestion,
59 ..
60 }) => {
61 println!("✗ Precision error:");
62 println!(" Expected: {} decimals", expected);
63 println!(" Actual: {} decimals", actual);
64 println!(" Suggestion: {}", suggestion);
65
66 // Recover by normalizing
67 let normalized = amount.normalize();
68 println!("\n✓ After normalizing: {}", normalized);
69 println!(" Precision OK: {}", normalized.check_precision().is_ok());
70 }
71 Err(e) => println!("✗ Unexpected error: {}", e),
72 }
73
74 // ========================================
75 // Invalid Rate Errors
76 // ========================================
77 println!("\n3. INVALID RATE ERRORS");
78 println!("----------------------");
79
80 // Valid rate
81 match Rate::<USD, EUR>::try_new(0.85) {
82 Ok(rate) => println!("✓ Valid rate: {}", rate.value()),
83 Err(e) => println!("✗ Error: {}", e),
84 }
85
86 // Invalid rates
87 let invalid_rates = vec![
88 ("negative", -1.0),
89 ("zero", 0.0),
90 ("NaN", f64::NAN),
91 ("infinity", f64::INFINITY),
92 ];
93
94 println!("\nInvalid rates:");
95 for (desc, value) in invalid_rates {
96 match Rate::<USD, EUR>::try_new(value) {
97 Ok(rate) => println!(
98 " {} ({}) → Unexpected success: {}",
99 desc,
100 value,
101 rate.value()
102 ),
103 Err(MoneyError::InvalidRate { reason, .. }) => {
104 println!(" {} ({}) → {}", desc, value, reason);
105 }
106 Err(e) => println!(" {} ({}) → Error: {}", desc, value, e),
107 }
108 }
109
110 // ========================================
111 // Error Suggestions
112 // ========================================
113 println!("\n4. ERROR RECOVERY SUGGESTIONS");
114 println!("------------------------------");
115
116 let errors = vec![
117 MoneyError::PrecisionError {
118 currency: "USD",
119 expected: 2,
120 actual: 5,
121 suggestion: "Use normalize() or round() to adjust precision".to_string(),
122 },
123 MoneyError::InvalidRate {
124 value: "-1.0".to_string(),
125 reason: "Rate must be positive".to_string(),
126 },
127 MoneyError::ParseError {
128 input: "abc".to_string(),
129 expected_currency: Some("USD"),
130 reason: "Invalid number format".to_string(),
131 },
132 ];
133
134 for error in errors {
135 println!("\nError: {}", error);
136 println!("Suggestion: {}", error.suggestion());
137 if let Some(currency) = error.currency() {
138 println!("Currency: {}", currency);
139 }
140 }
141
142 // ========================================
143 // Safe Division
144 // ========================================
145 println!("\n5. SAFE DIVISION");
146 println!("----------------");
147
148 let amount = Amount::<USD>::from_major(100);
149
150 // Division by zero is handled
151 let divisor = 0;
152 println!("Dividing {} by {}...", amount, divisor);
153
154 if divisor == 0 {
155 println!("✗ Cannot divide by zero!");
156 println!(" Handled before attempting division");
157 } else {
158 let result = amount / divisor;
159 println!("✓ Result: {}", result);
160 }
161
162 // Safe division with non-zero
163 let safe_divisor = 3;
164 let result = amount / safe_divisor;
165 println!("\nDividing {} by {}: {}", amount, safe_divisor, result);
166
167 // ========================================
168 // Pattern Matching on Errors
169 // ========================================
170 println!("\n6. PATTERN MATCHING");
171 println!("-------------------");
172
173 fn parse_and_handle(input: &str) -> MoneyResult<Amount<USD>> {
174 Amount::<USD>::from_str(input)
175 }
176
177 let inputs = vec!["123.45", "invalid", "999.99"];
178
179 for input in inputs {
180 print!("Parsing '{}': ", input);
181
182 match parse_and_handle(input) {
183 Ok(amount) => {
184 println!("✓ Success: {}", amount);
185 }
186 Err(MoneyError::ParseError { input, reason, .. }) => {
187 println!("✗ Parse error");
188 println!(" Input: '{}'", input);
189 println!(" Reason: {}", reason);
190 }
191 Err(e) => {
192 println!("✗ Other error: {}", e);
193 }
194 }
195 }
196
197 // ========================================
198 // Error Propagation with ?
199 // ========================================
200 println!("\n7. ERROR PROPAGATION");
201 println!("--------------------");
202
203 fn calculate_total(price_str: &str, quantity: i64) -> MoneyResult<Amount<USD>> {
204 let price = Amount::<USD>::from_str(price_str)?;
205 let total = price * quantity;
206 total.check_precision()?;
207 Ok(total)
208 }
209
210 match calculate_total("29.99", 3) {
211 Ok(total) => println!("✓ Total: {}", total),
212 Err(e) => println!("✗ Error: {}", e),
213 }
214
215 match calculate_total("invalid", 3) {
216 Ok(total) => println!("✓ Total: {}", total),
217 Err(e) => println!("✗ Error: {}", e),
218 }
219
220 // ========================================
221 // Recovering from Errors
222 // ========================================
223 println!("\n8. ERROR RECOVERY");
224 println!("-----------------");
225
226 fn parse_with_fallback(input: &str, fallback: Amount<USD>) -> Amount<USD> {
227 Amount::<USD>::from_str(input).unwrap_or(fallback)
228 }
229
230 let fallback = Amount::<USD>::from_major(0);
231
232 let inputs = vec!["123.45", "invalid", "67.89"];
233 for input in inputs {
234 let amount = parse_with_fallback(input, fallback);
235 println!("'{}' → {}", input, amount);
236 }
237
238 // ========================================
239 // Validation Before Operations
240 // ========================================
241 println!("\n9. VALIDATION");
242 println!("-------------");
243
244 fn safe_divide(amount: Amount<USD>, divisor: i64) -> MoneyResult<Amount<USD>> {
245 if divisor == 0 {
246 return Err(MoneyError::InvalidAmount {
247 currency: Some("USD"),
248 reason: "Cannot divide by zero".to_string(),
249 });
250 }
251
252 let result = amount / divisor;
253
254 // Check precision after division
255 result.check_precision()?;
256
257 Ok(result)
258 }
259
260 let amount = Amount::<USD>::from_major(100);
261
262 match safe_divide(amount, 0) {
263 Ok(result) => println!(" Division by 0: {}", result),
264 Err(e) => println!(" Division by 0: Error - {}", e),
265 }
266
267 match safe_divide(amount, 3) {
268 Ok(result) => println!(" Division by 3: {}", result),
269 Err(e) => println!(" Division by 3: Error - {}", e),
270 }
271
272 // ========================================
273 // Real-World: Parsing User Input
274 // ========================================
275 println!("\n10. REAL-WORLD: PARSING USER INPUT");
276 println!("-----------------------------------");
277
278 fn process_payment(amount_str: &str) -> MoneyResult<String> {
279 // Parse the amount
280 let amount = Amount::<USD>::from_str(amount_str)?;
281
282 // Validate it's positive
283 if amount.to_minor() <= 0 {
284 return Err(MoneyError::InvalidAmount {
285 currency: Some("USD"),
286 reason: "Payment amount must be positive".to_string(),
287 });
288 }
289
290 // Process the payment
291 let fee = (amount * 3) / 100; // 3% fee
292 let total = amount + fee;
293
294 Ok(format!(
295 "Payment: {}, Fee: {}, Total: {}",
296 amount, fee, total
297 ))
298 }
299
300 let test_inputs = vec!["100.00", "0", "-50", "abc", "250.50"];
301
302 for input in test_inputs {
303 println!("\nProcessing payment: '{}'", input);
304 match process_payment(input) {
305 Ok(summary) => println!(" ✓ {}", summary),
306 Err(e) => {
307 println!(" ✗ Error: {}", e);
308 let suggestion = e.suggestion();
309 println!(" Hint: {}", suggestion);
310 }
311 }
312 }
313
314 // ========================================
315 // Rounding to Fix Precision
316 // ========================================
317 println!("\n11. FIXING PRECISION WITH ROUNDING");
318 println!("-----------------------------------");
319
320 let amount = Amount::<USD>::from_major(10) / 3; // Creates excess precision
321
322 println!("Original: {}", amount);
323 println!(
324 "Precision check: {}",
325 if amount.check_precision().is_ok() {
326 "✓ OK"
327 } else {
328 "✗ Excess precision"
329 }
330 );
331
332 // Fix with rounding
333 let rounded = amount.round(RoundingMode::HalfUp);
334 println!("\nRounded: {}", rounded);
335 println!(
336 "Precision check: {}",
337 if rounded.check_precision().is_ok() {
338 "✓ OK"
339 } else {
340 "✗ Excess precision"
341 }
342 );
343
344 // Or normalize (uses banker's rounding)
345 let normalized = amount.normalize();
346 println!("\nNormalized: {}", normalized);
347 println!(
348 "Precision check: {}",
349 if normalized.check_precision().is_ok() {
350 "✓ OK"
351 } else {
352 "✗ Excess precision"
353 }
354 );
355
356 println!("\n=== All error handling examples completed! ===");
357}Sourcepub const fn timestamp_unix_secs(&self) -> Option<u64>
pub const fn timestamp_unix_secs(&self) -> Option<u64>
Returns the optional UNIX timestamp (seconds) metadata.
Examples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}Sourcepub const fn source(&self) -> Option<&'static str>
pub const fn source(&self) -> Option<&'static str>
Returns the optional static source identifier metadata.
Examples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}Sourcepub const fn with_timestamp_unix_secs(self, timestamp_unix_secs: u64) -> Self
pub const fn with_timestamp_unix_secs(self, timestamp_unix_secs: u64) -> Self
Returns a new Rate with the given UNIX timestamp (seconds) metadata set.
Existing metadata values not provided by this method are preserved.
Examples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}More examples
51fn main() {
52 println!("=== Typed Money - Global Currencies Example ===\n");
53
54 // 1. MAJOR FIAT CURRENCIES
55 println!("1. MAJOR FIAT CURRENCIES");
56 println!("------------------------");
57 let usd = Amount::<USD>::from_major(100);
58 let cad = Amount::<CAD>::from_major(135);
59 let chf = Amount::<CHF>::from_major(90);
60 let aud = Amount::<AUD>::from_major(150);
61 let nzd = Amount::<NZD>::from_major(160);
62
63 println!("USD: {} ({} decimals)", usd, USD::DECIMALS);
64 println!("CAD: {} ({} decimals)", cad, CAD::DECIMALS);
65 println!("CHF: {} ({} decimals)", chf, CHF::DECIMALS);
66 println!("AUD: {} ({} decimals)", aud, AUD::DECIMALS);
67 println!("NZD: {} ({} decimals)", nzd, NZD::DECIMALS);
68 println!();
69
70 // 2. ASIAN CURRENCIES
71 println!("2. ASIAN CURRENCIES");
72 println!("-------------------");
73 let cny = Amount::<CNY>::from_major(720);
74 let krw = Amount::<KRW>::from_major(130_000);
75 let sgd = Amount::<SGD>::from_major(135);
76 let hkd = Amount::<HKD>::from_major(780);
77 let twd = Amount::<TWD>::from_major(3100);
78 let inr = Amount::<INR>::from_major(8300);
79
80 println!("CNY: {} ({} decimals)", cny, CNY::DECIMALS);
81 println!("KRW: {} ({} decimals)", krw, KRW::DECIMALS);
82 println!("SGD: {} ({} decimals)", sgd, SGD::DECIMALS);
83 println!("HKD: {} ({} decimals)", hkd, HKD::DECIMALS);
84 println!("TWD: {} ({} decimals)", twd, TWD::DECIMALS);
85 println!("INR: {} ({} decimals)", inr, INR::DECIMALS);
86 println!();
87
88 // 3. EUROPEAN CURRENCIES
89 println!("3. EUROPEAN CURRENCIES");
90 println!("----------------------");
91 let eur = Amount::<EUR>::from_major(85);
92 let gbp = Amount::<GBP>::from_major(75);
93 let sek = Amount::<SEK>::from_major(1050);
94 let nok = Amount::<NOK>::from_major(1100);
95 let dkk = Amount::<DKK>::from_major(650);
96 let pln = Amount::<PLN>::from_major(400);
97 let czk = Amount::<CZK>::from_major(2300);
98 let huf = Amount::<HUF>::from_major(36_000);
99
100 println!("EUR: {} ({} decimals)", eur, EUR::DECIMALS);
101 println!("GBP: {} ({} decimals)", gbp, GBP::DECIMALS);
102 println!("SEK: {} ({} decimals)", sek, SEK::DECIMALS);
103 println!("NOK: {} ({} decimals)", nok, NOK::DECIMALS);
104 println!("DKK: {} ({} decimals)", dkk, DKK::DECIMALS);
105 println!("PLN: {} ({} decimals)", pln, PLN::DECIMALS);
106 println!("CZK: {} ({} decimals)", czk, CZK::DECIMALS);
107 println!("HUF: {} ({} decimals)", huf, HUF::DECIMALS);
108 println!();
109
110 // 4. AMERICAN CURRENCIES
111 println!("4. AMERICAN CURRENCIES");
112 println!("----------------------");
113 let brl = Amount::<BRL>::from_major(500);
114 let mxn = Amount::<MXN>::from_major(1700);
115 let ars = Amount::<ARS>::from_major(85_000);
116 let clp = Amount::<CLP>::from_major(90_000);
117
118 println!("BRL: {} ({} decimals)", brl, BRL::DECIMALS);
119 println!("MXN: {} ({} decimals)", mxn, MXN::DECIMALS);
120 println!("ARS: {} ({} decimals)", ars, ARS::DECIMALS);
121 println!("CLP: {} ({} decimals)", clp, CLP::DECIMALS);
122 println!();
123
124 // 5. AFRICAN/MIDDLE EASTERN CURRENCIES
125 println!("5. AFRICAN/MIDDLE EASTERN CURRENCIES");
126 println!("------------------------------------");
127 let zar = Amount::<ZAR>::from_major(1800);
128 let egp = Amount::<EGP>::from_major(3100);
129 let aed = Amount::<AED>::from_major(370);
130 let sar = Amount::<SAR>::from_major(375);
131 let ils = Amount::<ILS>::from_major(360);
132 let try_currency = Amount::<TRY>::from_major(3000);
133
134 println!("ZAR: {} ({} decimals)", zar, ZAR::DECIMALS);
135 println!("EGP: {} ({} decimals)", egp, EGP::DECIMALS);
136 println!("AED: {} ({} decimals)", aed, AED::DECIMALS);
137 println!("SAR: {} ({} decimals)", sar, SAR::DECIMALS);
138 println!("ILS: {} ({} decimals)", ils, ILS::DECIMALS);
139 println!("TRY: {} ({} decimals)", try_currency, TRY::DECIMALS);
140 println!();
141
142 // 6. CRYPTOCURRENCIES
143 println!("6. CRYPTOCURRENCIES");
144 println!("-------------------");
145 let btc = Amount::<BTC>::from_minor(100_000_000); // 1.00000000 BTC
146 let eth = Amount::<ETH>::from_minor(1_000_000_000_000_000_000); // 1.000000000000000000 ETH
147
148 println!("BTC: {} ({} decimals)", btc, BTC::DECIMALS);
149 println!("ETH: {} ({} decimals)", eth, ETH::DECIMALS);
150 println!();
151
152 // 7. CURRENCY CONVERSION EXAMPLES
153 println!("7. CURRENCY CONVERSION EXAMPLES");
154 println!("-------------------------------");
155
156 // USD to EUR
157 let usd_to_eur = Rate::<USD, EUR>::new(0.85)
158 .with_timestamp_unix_secs(1_700_000_000)
159 .with_source("ECB");
160 let eur_converted = usd.convert(&usd_to_eur);
161 println!(
162 "USD to EUR: {} → {} (rate: {})",
163 usd,
164 eur_converted,
165 usd_to_eur.value()
166 );
167
168 // EUR to GBP
169 let eur_to_gbp = Rate::<EUR, GBP>::new(0.87);
170 let gbp_converted = eur_converted.convert(&eur_to_gbp);
171 println!(
172 "EUR to GBP: {} → {} (rate: {})",
173 eur_converted,
174 gbp_converted,
175 eur_to_gbp.value()
176 );
177
178 // USD to JPY
179 let usd_to_jpy = Rate::<USD, JPY>::new(150.0);
180 let jpy_converted = usd.convert(&usd_to_jpy);
181 println!(
182 "USD to JPY: {} → {} (rate: {})",
183 usd,
184 jpy_converted,
185 usd_to_jpy.value()
186 );
187 println!();
188
189 // 8. ROUNDING EXAMPLES
190 println!("8. ROUNDING EXAMPLES");
191 println!("--------------------");
192 let usd_amount = Amount::<USD>::from_minor(12345); // $123.45
193 println!("Original: {}", usd_amount);
194 println!("Half Up: {}", usd_amount.round(RoundingMode::HalfUp));
195 println!("Half Down: {}", usd_amount.round(RoundingMode::HalfDown));
196 println!("Half Even: {}", usd_amount.round(RoundingMode::HalfEven));
197 println!("Floor: {}", usd_amount.round(RoundingMode::Floor));
198 println!("Ceiling: {}", usd_amount.round(RoundingMode::Ceiling));
199 println!();
200
201 // 9. CURRENCY METADATA
202 println!("9. CURRENCY METADATA");
203 println!("--------------------");
204 let currencies = [
205 ("USD", USD::CODE, USD::SYMBOL, USD::DECIMALS),
206 ("EUR", EUR::CODE, EUR::SYMBOL, EUR::DECIMALS),
207 ("JPY", JPY::CODE, JPY::SYMBOL, JPY::DECIMALS),
208 ("CNY", CNY::CODE, CNY::SYMBOL, CNY::DECIMALS),
209 ("BRL", BRL::CODE, BRL::SYMBOL, BRL::DECIMALS),
210 ("AED", AED::CODE, AED::SYMBOL, AED::DECIMALS),
211 ];
212
213 for (name, code, symbol, decimals) in currencies {
214 println!("{}: {} {} ({} decimals)", name, symbol, code, decimals);
215 }
216 println!();
217
218 // 10. TYPE SAFETY DEMONSTRATION
219 println!("10. TYPE SAFETY DEMONSTRATION");
220 println!("-----------------------------");
221 println!("✓ USD + USD = Valid");
222 println!("✓ EUR + EUR = Valid");
223 println!("✓ CAD + CAD = Valid");
224 println!("✗ USD + EUR = Compile Error!");
225 println!("✗ CAD + JPY = Compile Error!");
226 println!("✗ BRL + TRY = Compile Error!");
227 println!();
228
229 println!("=== Global Currencies Example Completed! ===");
230 println!("Total currencies supported: 30+");
231 println!("Regions covered: North America, Europe, Asia, South America, Africa, Middle East");
232 println!("Type safety: 100% compile-time currency mixing prevention");
233}Sourcepub const fn with_source(self, source: &'static str) -> Self
pub const fn with_source(self, source: &'static str) -> Self
Returns a new Rate with the given static source identifier set.
Existing metadata values not provided by this method are preserved.
Examples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}More examples
51fn main() {
52 println!("=== Typed Money - Global Currencies Example ===\n");
53
54 // 1. MAJOR FIAT CURRENCIES
55 println!("1. MAJOR FIAT CURRENCIES");
56 println!("------------------------");
57 let usd = Amount::<USD>::from_major(100);
58 let cad = Amount::<CAD>::from_major(135);
59 let chf = Amount::<CHF>::from_major(90);
60 let aud = Amount::<AUD>::from_major(150);
61 let nzd = Amount::<NZD>::from_major(160);
62
63 println!("USD: {} ({} decimals)", usd, USD::DECIMALS);
64 println!("CAD: {} ({} decimals)", cad, CAD::DECIMALS);
65 println!("CHF: {} ({} decimals)", chf, CHF::DECIMALS);
66 println!("AUD: {} ({} decimals)", aud, AUD::DECIMALS);
67 println!("NZD: {} ({} decimals)", nzd, NZD::DECIMALS);
68 println!();
69
70 // 2. ASIAN CURRENCIES
71 println!("2. ASIAN CURRENCIES");
72 println!("-------------------");
73 let cny = Amount::<CNY>::from_major(720);
74 let krw = Amount::<KRW>::from_major(130_000);
75 let sgd = Amount::<SGD>::from_major(135);
76 let hkd = Amount::<HKD>::from_major(780);
77 let twd = Amount::<TWD>::from_major(3100);
78 let inr = Amount::<INR>::from_major(8300);
79
80 println!("CNY: {} ({} decimals)", cny, CNY::DECIMALS);
81 println!("KRW: {} ({} decimals)", krw, KRW::DECIMALS);
82 println!("SGD: {} ({} decimals)", sgd, SGD::DECIMALS);
83 println!("HKD: {} ({} decimals)", hkd, HKD::DECIMALS);
84 println!("TWD: {} ({} decimals)", twd, TWD::DECIMALS);
85 println!("INR: {} ({} decimals)", inr, INR::DECIMALS);
86 println!();
87
88 // 3. EUROPEAN CURRENCIES
89 println!("3. EUROPEAN CURRENCIES");
90 println!("----------------------");
91 let eur = Amount::<EUR>::from_major(85);
92 let gbp = Amount::<GBP>::from_major(75);
93 let sek = Amount::<SEK>::from_major(1050);
94 let nok = Amount::<NOK>::from_major(1100);
95 let dkk = Amount::<DKK>::from_major(650);
96 let pln = Amount::<PLN>::from_major(400);
97 let czk = Amount::<CZK>::from_major(2300);
98 let huf = Amount::<HUF>::from_major(36_000);
99
100 println!("EUR: {} ({} decimals)", eur, EUR::DECIMALS);
101 println!("GBP: {} ({} decimals)", gbp, GBP::DECIMALS);
102 println!("SEK: {} ({} decimals)", sek, SEK::DECIMALS);
103 println!("NOK: {} ({} decimals)", nok, NOK::DECIMALS);
104 println!("DKK: {} ({} decimals)", dkk, DKK::DECIMALS);
105 println!("PLN: {} ({} decimals)", pln, PLN::DECIMALS);
106 println!("CZK: {} ({} decimals)", czk, CZK::DECIMALS);
107 println!("HUF: {} ({} decimals)", huf, HUF::DECIMALS);
108 println!();
109
110 // 4. AMERICAN CURRENCIES
111 println!("4. AMERICAN CURRENCIES");
112 println!("----------------------");
113 let brl = Amount::<BRL>::from_major(500);
114 let mxn = Amount::<MXN>::from_major(1700);
115 let ars = Amount::<ARS>::from_major(85_000);
116 let clp = Amount::<CLP>::from_major(90_000);
117
118 println!("BRL: {} ({} decimals)", brl, BRL::DECIMALS);
119 println!("MXN: {} ({} decimals)", mxn, MXN::DECIMALS);
120 println!("ARS: {} ({} decimals)", ars, ARS::DECIMALS);
121 println!("CLP: {} ({} decimals)", clp, CLP::DECIMALS);
122 println!();
123
124 // 5. AFRICAN/MIDDLE EASTERN CURRENCIES
125 println!("5. AFRICAN/MIDDLE EASTERN CURRENCIES");
126 println!("------------------------------------");
127 let zar = Amount::<ZAR>::from_major(1800);
128 let egp = Amount::<EGP>::from_major(3100);
129 let aed = Amount::<AED>::from_major(370);
130 let sar = Amount::<SAR>::from_major(375);
131 let ils = Amount::<ILS>::from_major(360);
132 let try_currency = Amount::<TRY>::from_major(3000);
133
134 println!("ZAR: {} ({} decimals)", zar, ZAR::DECIMALS);
135 println!("EGP: {} ({} decimals)", egp, EGP::DECIMALS);
136 println!("AED: {} ({} decimals)", aed, AED::DECIMALS);
137 println!("SAR: {} ({} decimals)", sar, SAR::DECIMALS);
138 println!("ILS: {} ({} decimals)", ils, ILS::DECIMALS);
139 println!("TRY: {} ({} decimals)", try_currency, TRY::DECIMALS);
140 println!();
141
142 // 6. CRYPTOCURRENCIES
143 println!("6. CRYPTOCURRENCIES");
144 println!("-------------------");
145 let btc = Amount::<BTC>::from_minor(100_000_000); // 1.00000000 BTC
146 let eth = Amount::<ETH>::from_minor(1_000_000_000_000_000_000); // 1.000000000000000000 ETH
147
148 println!("BTC: {} ({} decimals)", btc, BTC::DECIMALS);
149 println!("ETH: {} ({} decimals)", eth, ETH::DECIMALS);
150 println!();
151
152 // 7. CURRENCY CONVERSION EXAMPLES
153 println!("7. CURRENCY CONVERSION EXAMPLES");
154 println!("-------------------------------");
155
156 // USD to EUR
157 let usd_to_eur = Rate::<USD, EUR>::new(0.85)
158 .with_timestamp_unix_secs(1_700_000_000)
159 .with_source("ECB");
160 let eur_converted = usd.convert(&usd_to_eur);
161 println!(
162 "USD to EUR: {} → {} (rate: {})",
163 usd,
164 eur_converted,
165 usd_to_eur.value()
166 );
167
168 // EUR to GBP
169 let eur_to_gbp = Rate::<EUR, GBP>::new(0.87);
170 let gbp_converted = eur_converted.convert(&eur_to_gbp);
171 println!(
172 "EUR to GBP: {} → {} (rate: {})",
173 eur_converted,
174 gbp_converted,
175 eur_to_gbp.value()
176 );
177
178 // USD to JPY
179 let usd_to_jpy = Rate::<USD, JPY>::new(150.0);
180 let jpy_converted = usd.convert(&usd_to_jpy);
181 println!(
182 "USD to JPY: {} → {} (rate: {})",
183 usd,
184 jpy_converted,
185 usd_to_jpy.value()
186 );
187 println!();
188
189 // 8. ROUNDING EXAMPLES
190 println!("8. ROUNDING EXAMPLES");
191 println!("--------------------");
192 let usd_amount = Amount::<USD>::from_minor(12345); // $123.45
193 println!("Original: {}", usd_amount);
194 println!("Half Up: {}", usd_amount.round(RoundingMode::HalfUp));
195 println!("Half Down: {}", usd_amount.round(RoundingMode::HalfDown));
196 println!("Half Even: {}", usd_amount.round(RoundingMode::HalfEven));
197 println!("Floor: {}", usd_amount.round(RoundingMode::Floor));
198 println!("Ceiling: {}", usd_amount.round(RoundingMode::Ceiling));
199 println!();
200
201 // 9. CURRENCY METADATA
202 println!("9. CURRENCY METADATA");
203 println!("--------------------");
204 let currencies = [
205 ("USD", USD::CODE, USD::SYMBOL, USD::DECIMALS),
206 ("EUR", EUR::CODE, EUR::SYMBOL, EUR::DECIMALS),
207 ("JPY", JPY::CODE, JPY::SYMBOL, JPY::DECIMALS),
208 ("CNY", CNY::CODE, CNY::SYMBOL, CNY::DECIMALS),
209 ("BRL", BRL::CODE, BRL::SYMBOL, BRL::DECIMALS),
210 ("AED", AED::CODE, AED::SYMBOL, AED::DECIMALS),
211 ];
212
213 for (name, code, symbol, decimals) in currencies {
214 println!("{}: {} {} ({} decimals)", name, symbol, code, decimals);
215 }
216 println!();
217
218 // 10. TYPE SAFETY DEMONSTRATION
219 println!("10. TYPE SAFETY DEMONSTRATION");
220 println!("-----------------------------");
221 println!("✓ USD + USD = Valid");
222 println!("✓ EUR + EUR = Valid");
223 println!("✓ CAD + CAD = Valid");
224 println!("✗ USD + EUR = Compile Error!");
225 println!("✗ CAD + JPY = Compile Error!");
226 println!("✗ BRL + TRY = Compile Error!");
227 println!();
228
229 println!("=== Global Currencies Example Completed! ===");
230 println!("Total currencies supported: 30+");
231 println!("Regions covered: North America, Europe, Asia, South America, Africa, Middle East");
232 println!("Type safety: 100% compile-time currency mixing prevention");
233}Sourcepub const fn with_metadata(
self,
timestamp_unix_secs: u64,
source: &'static str,
) -> Self
pub const fn with_metadata( self, timestamp_unix_secs: u64, source: &'static str, ) -> Self
Convenience method to set both timestamp and source metadata at once.
Sourcepub fn inverse(&self) -> Rate<To, From>
pub fn inverse(&self) -> Rate<To, From>
Returns the inverse rate (To -> From).
§Examples
use typed_money::{Rate, USD, EUR};
let usd_to_eur = Rate::<USD, EUR>::new(0.85);
let eur_to_usd = usd_to_eur.inverse();
// Inverse of 0.85 is approximately 1.176Examples found in repository?
10fn main() {
11 println!("=== Currency Conversion Examples ===\n");
12
13 // ========================================
14 // Basic Conversion
15 // ========================================
16 println!("1. BASIC CONVERSION");
17 println!("-------------------");
18
19 let usd_amount = Amount::<USD>::from_major(100);
20 println!("Starting amount: {}", usd_amount);
21
22 // Create an exchange rate: 1 USD = 0.85 EUR
23 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
24 println!("Exchange rate: 1 USD = 0.85 EUR");
25
26 // Convert
27 let eur_amount = usd_amount.convert(&usd_to_eur);
28 println!("Converted amount: {}", eur_amount);
29 println!("(${} × 0.85 = €{})\n", 100, eur_amount.to_major_floor());
30
31 // ========================================
32 // Inverse Rates
33 // ========================================
34 println!("2. INVERSE RATES");
35 println!("----------------");
36
37 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
38 println!("USD → EUR rate: {}", usd_to_eur.value());
39
40 // Get the inverse rate automatically
41 let eur_to_usd = usd_to_eur.inverse();
42 println!("EUR → USD rate (inverse): {}", eur_to_usd.value());
43 println!("(1 / 0.85 = ~1.176)\n");
44
45 // Converting back
46 let original_usd = Amount::<USD>::from_major(100);
47 let eur = original_usd.convert(&usd_to_eur);
48 let back_to_usd = eur.convert(&eur_to_usd);
49
50 println!("Original: {}", original_usd);
51 println!("To EUR: {}", eur);
52 println!("Back to USD: {}", back_to_usd);
53 println!("(Should be approximately the same)\n");
54
55 // ========================================
56 // Multiple Conversions
57 // ========================================
58 println!("3. MULTIPLE CONVERSIONS");
59 println!("-----------------------");
60
61 let usd = Amount::<USD>::from_major(1000);
62 println!("Starting with: {}", usd);
63
64 // Define multiple rates
65 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
66 let usd_to_gbp = Rate::<USD, GBP>::new(0.73);
67 let usd_to_jpy = Rate::<USD, JPY>::new(110.0);
68
69 println!("\nExchange rates:");
70 println!(" 1 USD = {} EUR", usd_to_eur.value());
71 println!(" 1 USD = {} GBP", usd_to_gbp.value());
72 println!(" 1 USD = {} JPY", usd_to_jpy.value());
73
74 println!("\nConversions:");
75 let eur = usd.convert(&usd_to_eur);
76 let gbp = usd.convert(&usd_to_gbp);
77 let jpy = usd.convert(&usd_to_jpy);
78
79 println!(" {} → {}", usd, eur);
80 println!(" {} → {}", usd, gbp);
81 println!(" {} → {}", usd, jpy);
82
83 // ========================================
84 // Chained Conversions
85 // ========================================
86 println!("\n4. CHAINED CONVERSIONS");
87 println!("----------------------");
88
89 println!("Converting USD → EUR → GBP");
90
91 let usd = Amount::<USD>::from_major(100);
92 let usd_to_eur = Rate::<USD, EUR>::new(0.85);
93 let eur_to_gbp = Rate::<EUR, GBP>::new(0.86);
94
95 println!("Starting: {}", usd);
96 let eur = usd.convert(&usd_to_eur);
97 println!("After USD→EUR: {}", eur);
98 let gbp = eur.convert(&eur_to_gbp);
99 println!("After EUR→GBP: {}", gbp);
100 println!("(${} × 0.85 × 0.86 = £{})\n", 100, gbp.to_major_floor());
101
102 // ========================================
103 // Rate Metadata for Auditability
104 // ========================================
105 println!("5. RATE METADATA FOR AUDITABILITY");
106 println!("----------------------------------");
107
108 // Create a rate with metadata
109 let rate = Rate::<USD, EUR>::new(0.85)
110 .with_timestamp_unix_secs(1700000000)
111 .with_source("ECB"); // European Central Bank
112
113 println!("Rate: {}", rate.value());
114 println!("Timestamp: {:?}", rate.timestamp_unix_secs());
115 println!("Source: {:?}", rate.source());
116
117 let amount = Amount::<USD>::from_major(1000);
118 let converted = amount.convert(&rate);
119 println!(
120 "\nConverted {} to {} using rate from {:?}",
121 amount,
122 converted,
123 rate.source().unwrap_or("unknown")
124 );
125
126 // ========================================
127 // Real-World Example: International Payment
128 // ========================================
129 println!("\n6. REAL-WORLD EXAMPLE: INTERNATIONAL PAYMENT");
130 println!("---------------------------------------------");
131
132 // Customer pays in USD
133 let payment_usd = Amount::<USD>::from_major(250);
134 println!("Customer payment: {}", payment_usd);
135
136 // Current exchange rate (would come from an API in production)
137 let current_rate = Rate::<USD, EUR>::new(0.92)
138 .with_timestamp_unix_secs(1700000000)
139 .with_source("API");
140
141 // Convert to EUR
142 let payment_eur = payment_usd.convert(¤t_rate);
143 println!("Converted to EUR: {}", payment_eur);
144
145 // Calculate fees
146 let fee_percentage = 3; // 3% transaction fee
147 let fee = (payment_eur * fee_percentage) / 100;
148 println!("Transaction fee ({}%): {}", fee_percentage, fee);
149
150 let final_amount = payment_eur - fee;
151 println!("Final amount to recipient: {}", final_amount);
152
153 println!("\nTransaction summary:");
154 println!(" Original: {}", payment_usd);
155 println!(
156 " Rate: {} (from {:?})",
157 current_rate.value(),
158 current_rate.source().unwrap_or("N/A")
159 );
160 println!(" Converted: {}", payment_eur);
161 println!(" Fee: -{}", fee);
162 println!(" Final: {}", final_amount);
163
164 // ========================================
165 // Type Safety with Conversions
166 // ========================================
167 println!("\n7. TYPE SAFETY");
168 println!("--------------");
169
170 println!("✓ Can only convert with matching rate types");
171 println!("✓ USD amount requires Rate<USD, X>");
172 println!("✗ Cannot use Rate<EUR, GBP> on USD amount (compile error!)");
173 println!("\nThe type system ensures you always use the correct exchange rate!");
174
175 // This would NOT compile:
176 // let usd = Amount::<USD>::from_major(100);
177 // let wrong_rate = Rate::<EUR, GBP>::new(0.86);
178 // let invalid = usd.convert(&wrong_rate); // Compile error!
179
180 println!("\n=== All conversion examples completed! ===");
181}