A procedural macro-based library that transforms standard arithmetic operations into their checked equivalents at compile time, preventing overflow, underflow, and division by zero errors.
safe-math
provides:
- Compile-time transformation of arithmetic operations into checked variants without runtime overhead
- Comprehensive error handling via
Result
types - Support for custom types through derive macros
The #[safe_math]
attribute transforms arithmetic operations into their checked equivalents:
use safe_math::safe_math;
#[safe_math]
fn add(a: u8, b: u8) -> Result<u8, safe_math::SafeMathError> {
Ok(a + b) // Automatically uses checked addition
}
assert_eq!(add(10, 20), Ok(30));
assert_eq!(add(255, 1), Err(safe_math::SafeMathError::Overflow));
All basic arithmetic operations are supported:
- Addition (
+
,+=
) - Subtraction (
-
,-=
) - Multiplication (
*
,*=
) - Division (
/
,/=
) - Remainder (
%
,%=
)
Operations return SafeMathError
for exceptional cases:
pub enum SafeMathError {
Overflow, // Result exceeds type bounds
DivisionByZero, // Division or remainder by zero
InfiniteOrNaN, // Result is infinite or NaN (floating-point types)
NotImplemented, // Missing trait implementation (derive feature)
}
Built-in support for:
- Unsigned integers:
u8
throughu128
,usize
- Signed integers:
i8
throughi128
,isize
- Floating point:
f32
,f64
(with infinity/NaN handling)
Enable the derive
feature to implement safe arithmetic for custom types:
use safe_math::SafeMathOps;
#[derive(SafeMathOps)]
#[SafeMathOps(add, sub, mul, div, rem)]
struct MyNumber(u32);
#[safe_math]
fn calculate(a: MyNumber, b: MyNumber) -> Result<MyNumber, safe_math::SafeMathError> {
Ok(a + b)
}
Note: For the derive to work, your type must implement both the standard arithmetic traits
(like Add
, Sub
, Mul
, Div
, Rem
) and their checked counterparts (like CheckedAdd
,
CheckedSub
, CheckedMul
, CheckedDiv
, CheckedRem
) from the num-traits
crate.
This requirement exists because without knowing what a type represents, it's impossible to determine what operations are safe to perform or what constitutes a "checked" operation.
Use safe_math_block!
to apply checked operations to a specific block of code:
use safe_math::safe_math_block;
fn process_numbers(a: u32, b: u32, c: u32) -> Result<u32, safe_math::SafeMathError> {
// Only this block uses checked arithmetic
let result = safe_math_block!({
let product = a * b;
let sum = product + c;
sum / b
});
Ok(result)
}
This is useful when you want to:
- Apply safe arithmetic to specific expression
- Mix checked and unchecked operations in the same function
Planned upcoming features:
-
Option-returning functions Support for functions that return
Option<T>
instead ofResult<T, SafeMathError>
. -
Crate-level macro support Ability to apply
#[safe_math]
to the entire crate with a single attribute:
// main.rs or lib.rs
#![safe_math]
fn demo(a: u32, b: u32) -> Result<u32, safe_math::SafeMathError> {
Ok(a * b + 1)
}
Licensed under either:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT license (LICENSE-MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you shall be dual licensed as above, without any additional terms or conditions.