Crates.io | cadd |
lib.rs | cadd |
version | 0.1.0 |
created_at | 2025-06-28 02:13:03.158558+00 |
updated_at | 2025-09-16 10:47:13.552727+00 |
description | Painless checked arithmetics and conversions |
homepage | |
repository | https://github.com/Riateche/cadd |
max_upload_size | |
id | 1729431 |
size | 66,580 |
cadd
: painless checked arithmetics and conversionsFeatures:
ops
:
Checked arithmetics with Result
and backtracesCinto
:
TryInto
with better error messages and backtraces for number conversionsSaturatingInto
:
infallible number conversion that returns the closest valid valuenon_zero
and to_non_zero()
:
conversion to NonZero
with Result
and backtraces.into_type::<T>()
as an alternative to into()
and try_into()
without type inference errorsIn Rust, most of the basic arithmetic operations (like a + b
) are unchecked in Release mode.
This means that they can silently overflow. This is great for performance, but may not be so great
when your application bills the customer the wrong amount of money.
In addition, some of the operations (like a / b
and a.ilog(b)
) will panic if their preconditions
are unmet. This can bring down the whole process if you're not careful. If the inputs are untrusted,
a checked alternative should be used.
Thankfully, Rust offers great capabilities for checked arithmetics.
For every operation that can overflow or otherwise fail,
the standard library contains a function with the checked_
prefix that returns Option
.
Let's suppose we have some (almost) production-ready code:
async fn handle_request(&self) -> anyhow::Result<()> {
let price = self.price()?;
let discount_rate = self.discount_rate();
let amount = price - discount_rate * price / 100;
self.bill_user(amount).await?;
Ok(())
}
After it billed some user $18446744073709551596 by accident, we decided to use checked arithmetics in our business logic:
use anyhow::Context as _;
let amount = discount_rate
.checked_mul(price)
.and_then(|v| v.checked_div(100))
.and_then(|v| price.checked_sub(v))
.context("amount overflow")?;
Now this is production ready! And also quite painful to look at.
cadd
cadd
provides traits and functions that make checked arithmetics just as easy to do as
unchecked ones. Just add "c" to the name of the corresponding unchecked function
and import it:
use cadd::ops::{csub, Cmul, Cdiv};
let amount = csub(
price,
discount_rate.cmul(price)?.cdiv(100)?,
)?;
Not only it's much more consise, but it also returns a Result
with an error type that contains
the failed operation, its arguments, and a backtrace:
overflow: 100 - 200
stack backtrace:
0: std::backtrace_rs::backtrace::libunwind::trace
...
You can also freely choose between method form
(a.cadd(b)
)
and free function form (cadd(a, b)
)
as you see fit.
And it's not just operators (+
, -
, etc). For every checked_*
function in std
, there is a corresponding
function in cadd
: cdiv_euclid
,
cilog2
, and so on.
See ops
module documentation for more information.
License: MIT OR Apache-2.0