Expand description
§cadd
: painless checked arithmetics and conversions
Features:
ops
: Checked arithmetics withResult
and backtracesCinto
:TryInto
with better error messages and backtraces for number conversionsSaturatingInto
: infallible number conversion that returns the closest valid valuenon_zero
andto_non_zero()
: conversion toNonZero
withResult
and backtraces.into_type::<T>()
as an alternative tointo()
andtry_into()
without type inference errors
§Intro to checked and unchecked math
In 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.
§Checked operations with 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.
Modules§
- convert
- Converting values to another type.
- ops
- Checked operations on numbers.
- prelude
- Exports most of the library’s traits and functions.
Structs§
- Error
- A general error with a message and a backtrace (if enabled).
Type Aliases§
- Result
Result
with error type defaulting tocadd::Error
.