Saturating integers
satint provides small no_std, no-alloc wrappers around Rust primitive
integers that use saturating arithmetic for ordinary integer operations.
The crate exposes signed aliases (Si8, Si16, Si32, Si64, Si128) and
unsigned aliases (Su8, Su16, Su32, Su64, Su128), plus matching
constructor functions (si8, su32, and so on).
Why
Rust already has primitive methods like u8::saturating_add, but using them
consistently can be noisy when a value should saturate by default. satint
makes that behavior part of the type:
use ;
assert_eq!;
assert_eq!;
let mut health = MAX;
health += 1;
assert_eq!;
Supported Types
Signed:
use ;
use ;
Unsigned:
use ;
use ;
Each alias is a transparent wrapper over core::num::Saturating<T>.
Arithmetic
+, -, and * saturate for same-width values. The right-hand side can be
either another wrapper or a matching primitive:
use ;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
let mut value = su16;
value += 5;
value *= 3;
assert_eq!;
Division And Remainder
Division and remainder are intentionally checked methods rather than / and
% operator impls. They return None for division by zero, and for signed
overflow such as MIN / -1.
use ;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Conversions
Lossless widening conversions use From / Into:
use ;
let signed: Si32 = si8.into;
let unsigned: Su32 = su8.into;
let unsigned_to_signed: Si32 = new.into;
assert_eq!;
assert_eq!;
assert_eq!;
Fallible narrowing and cross-sign conversions use TryFrom:
use ;
assert_eq!;
assert!;
assert_eq!;
assert!;
Clamping conversions use SaturatingFrom or SaturatingInto:
use ;
assert_eq!;
assert_eq!;
let value: Su8 = su16.saturating_into;
assert_eq!;
Same-width signedness flips have shorthand inherent methods that forward to the saturating conversions above:
use ;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Primitive integers can also be used as the source:
use ;
let signed: Si32 = 42_i32.saturating_into;
let unsigned: Su32 = 42_i32.saturating_into;
assert_eq!;
assert_eq!;
Float Conversions
f32 and f64 can be converted into any signed or unsigned wrapper, in both
saturating and fallible forms. Both truncate toward zero on the way to an
integer.
SaturatingFrom mirrors Rust's as cast: NaN becomes zero, infinities
saturate to MIN / MAX (or 0 / MAX for unsigned), and finite
out-of-range values clamp to the closest endpoint.
use ;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
TryFrom rejects NaN, ±Inf, and any finite value whose truncated form
falls outside the destination's range, returning TryFromFloatError.
use ;
assert_eq!;
assert!;
assert!;
assert!;
let _: TryFromFloatError = try_from.unwrap_err;
The reverse direction — wrapper to float — is provided as From only for
widths that round-trip exactly: Si8, Si16, Su8, Su16 for f32, and
those plus Si32, Su32 for f64. Wider integers are not supported as
sources because not every value would survive the cast losslessly.
use ;
let as_f32: f32 = si16.into;
let as_f64: f64 = su32.into;
assert_eq!;
assert_eq!;
Widening Arithmetic
Same-sign wider-left-hand-side + and - are supported when the right-hand
side always fits in the left-hand side:
use ;
assert_eq!;
assert_eq!;
This is intentionally one-directional: the wider type must be on the left.
Constants And Iterators
Concrete aliases provide MIN, MAX, ZERO, and ONE.
Sum and Product are implemented for scalar values and references:
use ;
let values = ;
assert_eq!;
assert_eq!;
Optional serde Support
Enable the serde feature to serialize and deserialize scalar values as their inner integer representation:
[]
= { = "0.1", = ["serde"] }
The feature depends on serde without enabling serde's default features, so it remains compatible with no_std users.
no_std
satint is #![no_std] and does not use alloc.
Panics
No operation in this crate panics. Arithmetic operators saturate, division and
remainder are exposed only as checked_div / checked_rem returning Option,
and conversions are either lossless (From), fallible (TryFrom), or
clamping (SaturatingFrom / SaturatingInto). The crate is also
#![forbid(unsafe_code)].
Limitations
- Wrapped values are integers only — there are no floating-point wrappers.
Float ↔ integer conversions are provided through
SaturatingFrom,TryFrom, andFrom(lossless cases only). - Only
+,-,*, their assignment forms, and signed unary-are operator overloads. - Division and remainder are available only through
checked_divandchecked_rem. - Cross-width arithmetic is limited to same-sign wider-left-hand-side
+and-. - Mixed signed/unsigned arithmetic is not implemented directly. Convert first
with
From,TryFrom, or the saturating conversion traits. - Saturation is not error reporting. If you need to detect overflow, use primitive checked arithmetic or fallible conversions where appropriate.
License
Licensed under either of MIT or Apache-2.0, at your option.