#currency #money #amount #macro #conversion #decimal #arithmetic

oxydized-money-macros

为 oxydized-gains 提供便捷宏的配套库

2 个不稳定版本

0.2.0 2024 年 3 月 3 日
0.1.0 2024 年 3 月 3 日

金融 分类中排名 #115

MIT 许可证

10KB

Oxydized Money 💵 ↔ 💶

Build Test Clippy Doc

Crates.io Docs.rs Crates.io Crates.io

该库旨在提供数据类型来操作特定货币的金额、在货币之间转换金额并确保任何计算都在相同货币的金额上执行。

动机

引入此库是因为所有已知的现有替代方案都有一些显著的缺点

  • 使用原生浮点类型如 f32f64 会因其缺乏精度而受到影响。
  • 使用 rust_decimal::Decimal 解决了这个问题,但并不能阻止在不同货币中添加金额。
  • 使用 rusty_money::Money 虽然略好,但并不能真正解决转换问题,因为在不同货币的金额上进行算术操作会引发恐慌。

Rust 专注于适当的错误处理,所有这些选项都感觉像是一种妥协。该库旨在通过提供三种不同的数据类型来改进这一点

  • Amount 用于存储给定货币的金额。
  • CurrencyError 用于表示在 Amount 上进行算术操作期间发生的任何错误(货币不匹配等)。
  • AmountResult 用于存储算术操作的结果(要么是 Amount,要么是 CurrencyError)。

算术操作被定义为这些三种类型几乎无缝地交互。然而,在执行操作时,输出类型始终反映了是否可能发生错误。不会失败的操作将输出 Amount,而可能失败的操作将输出 AmountResult。在获取底层的 Amount 之前,需要正确检查 AmountResult 中的错误。

不再有 🦶-枪

示例

use oxydized_money_macros::{eur, usd, dec};
use oxydized_money::{
    Currency::{EUR,USD},
    CurrencyError,
    Decimal,
};

// Amount(USD)
let capital = usd!(10_000);

// Decinal
let exchange_rate = dec!(0.928);

// Amount(EUR)
let converted = capital.converted_to(EUR, exchange_rate);

// Amount(EUR)
let fees = eur!(15.2);

// Amount(EUR) + Amount(EUR) => AmountResult(EUR)
let subtotal = converted + fees;

// Amount(EUR) * Decimal => Amount(EUR)
let extras = eur!(50) * dec!(2);

// AmountResult(EUR) + Amount(EUR) => AmountResult(EUR)
let total = subtotal + extras;

// Comparing AmountResult with Amounts
assert_eq!(total, eur!(9_395.200));
#
// AmountResult(EUR) + Amount(USD) => AmountResult(Mismatch(EUR,USD))
let oops = total + usd!(20);

// Comparing AmountResult with CurrencyError
assert_eq!(oops, CurrencyError::Mismatch(EUR,USD));

// AmountResult(Mismatch(EUR,USD)) + Amount(USD) => AmountResult(Mismatch(EUR,USD))
let oh_my = oops + usd!(200);
assert_eq!(oh_my, CurrencyError::Mismatch(EUR,USD));

// "Everything, everywhere, all at once."
assert_eq!(
    usd!(10_000).converted_to(EUR, dec!(0.928)) + eur!(15.2) + eur!(50)*dec!(2),
    eur!(9_395.200)
);

支持的操作

二进制运算

数量

左操作数 运算符 右操作数 输出
数量 * 十进制 数量
数量 / 十进制 结果数量
数量 {+,-} 数量 结果数量
数量 {+,-} 结果数量 结果数量
数量 {==,!=} 数量 布尔值
数量 {==,!=} 结果数量 布尔值
数量 {<,>,>=,<= } 数量 布尔值

结果数量

左操作数 运算符 右操作数 输出
结果数量 * 十进制 结果数量
结果数量 / 十进制 结果数量
结果数量 {+,-} 数量 结果数量
结果数量 {+,-} 结果数量 结果数量
结果数量 {==,!=} 数量 布尔值
结果数量 {==,!=} 结果数量 布尔值
结果数量 {==,!=} 货币错误 布尔值

货币错误

左操作数 运算符 右操作数 输出
货币错误 {==,!=} 结果数量 布尔值
货币错误 {==,!=} 货币错误 布尔值

一元运算

数量

运算符 操作数 输出
- 数量 数量

结果数量

运算符 操作数 输出
- 结果数量 结果数量

依赖项

~550–770KB
~15K SLoC