simple_money 0.4.0

Down-to-earth money and currency implementation written in Rust.
Documentation
# Brief description
"Down-to-earth" (explained further below) money [^fowler] and currency implementation written in Rust.

See further below for more detailed design considerations.
[^fowler]: Money consists of an amount and a Currency,
as described by Martin Fowler in his [Money EAA Pattern](https://martinfowler.com/eaaCatalog/money.html).


# Usage

```rust
// You create a Currency either with a string code ...
let eur = Currency::new("EUR", 2)?;
// ... or a byte array ...
let kwt = Currency::new_using_bytes(b"KWD", 2)?;
// ... you need a byte array also to create a constant (compiler doesn't allow unwrap) ...
const EUR: Currency = Currency::new_using_bytes_const(b"EUR", 2);

// ... and use either to instantiate Money instances:
let money1 = Money { full_amount_as_minor: 12_95, currency: eur };
let money2 = Money { full_amount_as_minor: 15_99, currency: EUR };
let result =  money1 + money2;
```

[Project page on crates.io](https://crates.io/crates/simple_money)

# Other implementations

Simple Money has similar implementations in other programming languages.
There's a [_Simple Money_ project page on BitBucket](https://bitbucket.org/afischl/workspace/projects/MONEY), but I haven't published all of them.


#  Design considerations

Unless otherwise noted, the design considerations apply to all implementations, regardless of programming language.

## Overview

The "down-to-earth" in the brief description above boils down to:

* no fractional minor units (e.g. one dollar has 100 cents, but there's no half cent)[^fracminor]
* Monetary amount and currency always go together, just as suggested in Martin Fowler (2002) [_Patterns of Enterprise Application Architecture_]https://martinfowler.com/books/eaa.html, p. 488
* Intentionally no currency conversion (conversion rates are constantly changing and depend on external sources such as rate curves on the stock exchange)

Safe to use API:

* value object (concrete class), see further below
* no floating-point types in the API (`float`/`f32` or `double`/`f64`), just stores the whole amount converted to the minor unit (cents, pence, …)
* no accidental rounding (API forces you to either deal with division reminders or specify a rounding mode beforehand)

Compact size (not that relevant for all programming languages):

* small[^small] and copyable (if the programming language supports this) structs…
  * the whole amount converted to the minor unit (cents, pence, …) is stored in a single `long`/`i64`
  * In programming languages without shared immutable Strings, the `Currency` fits into four bytes
* …but still reasonably large enough minimum/maximum amounts (the whole US national dept in cents fits in hundreds of times in an `long`/`i64`)

Other design decisions:

* no dependencies (either none at all or none when using it, depending on implementation variant, e.g. the Java variant has no transitive dependencies)
* no silent overflow --- although "reasonably sized" (as stated above), the functions will throw an exception (Rust: panic) in the unlikely event of an overflow (even in release builds)


## Why runtime checks?

The implementations in statically typed programming languages might, just might, have leveraged the type system for the currencies, but I decided against it:

* simpler API: arithmetic operations intentionally work on and between `Money` instances for simplicity (returning `Optional`s for all operations is too cumbersome; I only have the division return a `DivisionResult` or similar type)
* locking down via the type system is too problematic once you go down the rabbit hole (see also [why not having currencies as type parameters?]https://deque.blog/2017/08/22/a-follow-up-of-the-study-of-4-money-class-designs-why-not-having-currencies-as-type-parameters/)
* drawback of the runtime checks: runtime exceptions can easily be ignored by a developer – do consider implementing Ward Cunningham's _money bag_ if you have the need to mix currencies frequently


## Value class

This class is a _value object_/_concrete class_:

* no identity-based equality, see e.g. Eric Evans (2003) _Domain Driven Design_, page 97 and Martin Fowler (2002) [_Patterns of Enterprise Application Architecture_]https://martinfowler.com/books/eaa.html, page 486
* immutable, except for Rust and C++, where the bindings (“variables”) have mutability or immutability (C++: const correctness)
* no inheritance/polymorphism, see Bjarne Stroustrup, _The C++ Programming Language, 4th edition_, page 478[^cpp4] _16.3.4 The Significance of Concrete Classes_

Quote from "The C++ Programming Language, 4th edition" (Bjarne Stroustrup):
> Concrete types have also been called value types and their use
> value-oriented programming. Their model of use and the "philosophy" behind
> their design are quite different from what is often called object-oriented
> programming (§3.2.4, Chapter 21).
>
> The intent of a concrete type is to do a single, relatively simple thing
> well and efficiently. It is not usually the aim to provide the user with
> facilities to modify the behavior of a concrete type. In particular,
> concrete types are not intended to display run-time polymorphic behavior
(see §3.2.3, §20.3.2).

(16.3.4 The Significance of Concrete Classes, page 478)

Note that Stroustrup's concrete types / value types are not necessarily immutable,
contrary to the value types in Java or other languages which share objects across multiple places.
In C++ (and Rust), the bindings (“variables”) have mutability or immutability (const correctness).

[^fracminor]: Of course, there are use cases where you want exactly that,
use something like [rusty-money](https://crates.io/crates/rusty-money) for that.

[^small]: I'll refer to the [C++ Core Guidelines]https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
here, which deems `2 * sizeof(void*)` as "cheaply copyable" --- this should be equivalent to
`mem::size_of::<usize>` in Rust (2 * 64bits on an 64bit architecture).

[^cpp4]: Quote from "The C++ Programming Language, 4th edition" (Bjarne Stroustrup):
> Concrete types have also been called value types and their use
> value-oriented programming. Their model of use and the "philosophy" behind
> their design are quite different from what is often called object-oriented
> programming (§3.2.4, Chapter 21).
>
> The intent of a concrete type is to do a single, relatively simple thing
> well and efficiently. It is not usually the aim to provide the user with
> facilities to modify the behavior of a concrete type. In particular,
> concrete types are not intended to display run-time polymorphic behavior
(see §3.2.3, §20.3.2).

(16.3.4 The Significance of Concrete Classes, page 478)


# Comparison to similar libraries
Here are two alternatives I've found:
- [steel-cent]https://crates.io/crates/steel-cent
  - uses an i64 for the amount, just like this implementation
  - has the same precision as the minor amount allows (no "half Cents")
  - its currency has the `Copy` trait and is as small as mine
  - the ISO currencies are provided, but IntelliJ's Rust plugin fails to see them (works in the terminal though)
- [rusty-money]https://crates.io/crates/rusty-money:
  - uses its own 128 representation for the amount
  - has more precision than available by the minor amount
  - its currency...
    - has lots of fields, ...
    - ... but the ISO currencies are provided ready to use
    - has the `Copy` trait, but is eighty bytes in size
  - is bristling with features (e.g. exchange rates?)