[](https://docs.rs/cadd/latest/cadd/)
[](https://crates.io/crates/cadd)
[](https://github.com/Riateche/cadd#license)
# cadd
## `cadd`: painless checked arithmetics and conversions
Features:
* [`ops`]: checked arithmetics with `Result`, informative errors, and backtrace.
* [`Cinto`](convert::Cinto): `TryInto` alternative for type conversions with better error messages and backtrace.
Works for integer types, other primitives, arrays, and string-like types.
* [`SaturatingInto`](convert::SaturatingInto):
infallible number conversion that returns the closest valid value.
* [`non_zero`](convert::non_zero) and [`to_non_zero()`](convert::ToNonZero):
conversion to [`NonZero`] with `Result`, informative errors, and backtrace.
* <code>.[into_type](convert::IntoType)::<T>()</code>
as an alternative to `into()` and `try_into()` without type inference errors.
* `no_std` support (`alloc` is still required).
## Introduction
Rust generally offers amazing capability to create safe, correct programs. However, since it is still
a systems programming language, there are still a few aspects where the "default" or the easiest way
to do something is the cheapest, but not always the correct one. One of the most ubiquitous example
is the behavior of arithmetic operations on integer types and casts between them:
* Many arithmetic operators (`+`, `-`, `*`, ...) and some functions (like `.pow()`) are
*unchecked* in Release mode. This means that they can silently overflow and wrap, producing a value
that is not the true output of the operation.
* Some of the operations (like `a / b` and `a.ilog(b)`) will panic if their preconditions
are unmet.
* `as` conversion between integer types will silently truncate values as necessary to fit the output type.
It's also capable of reinterpreting signed values as unsigned and vice versa, producing a value that
is not equal to the input.
Sometimes this behavior is fine. However, there are many cases where performance is not as important
as correctness. For most high level applications, calculating the values precisely is much more important,
as these values may represent things like amount of money or amount of physical goods.
Arguably, **checked math and conversions should be the default**. A faster, but potentially wrapping or
truncating alternative should only be chosen in specific cases, after ensuring that it will not cause
a logic bug.
Rust's core library provides very good APIs for checked operations. The only problem with them is that
they require much more verbose code. Compare a simple `a + b` with a properly done checked addition:
`a.checked_add(b).ok_or(Error::Overflow)?`. Any non-trivial code quickly becomes a wall of checked
calls and numerous error conversions.
This is where `cadd` comes in. This crate aims to provide a set of APIs that are (almost)
as easy to use as the basic operations, while being a safe, correct default. These functions
never wrap, truncate, reinterpret, or panic.
Any errors returned by `cadd` will contain as much information as possible (to a reasonable limit)
and will also capture a backtrace if it's enabled. This makes it easy to integrate it into
any error handling approach, be it custom error types or "catch-all" errors like `anyhow`.
## Example
The easiest, but error-prone approach:
```rust
let amount = price - discount_rate * price / 100;
let output = amount as u32;
```
A safe approach that uses `std` checked functions and returns a non-informative error on overflow:
```rust
let amount = discount_rate
.checked_mul(price)
.and_then(|v| v.checked_div(100))
.and_then(|v| price.checked_sub(v))
.ok_or_else(|| Error::Overflow)?;
In order to eliminate unintended side effects, wraps, truncations, and signed-vs-unsigned reinterpretation,
it's recommended to set the following clippy lints to `warn` level:
- `arithmetic_side_effects`
- `cast_possible_wrap`
- `cast_precision_loss`
- `cast_sign_loss`
## Development tips
### Updating generated code in `ops.rs`
```
cargo run -p cadd_generator -- . && cargo fmt && cargo clippy && cargo doc
```
### Updating `README.md`
```
cargo install cargo-readme
cargo readme --output README.md
```
## License
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.