Back

Wrapping arithmetic in Rust

One of Rusts great feature is that it catches integer overflows at runtime and panics rather than wraps (in debug builds). I recommend you read Huon’s blog post about this from a couple years ago.

While this is a desirable behaviour in general, integer overflows are commonly used when implementing cryptography primitives. Rust offers wrapping alternatives such as wrapping_add etc. to allow wrapping behaviour. However, this makes code very hard to read, e.g. let c = a + b is easier to read than let c = a.wrapping_add(b).

Other wrapping arithmetic

Rust itself provides a wrapping integer type in std::num::Wrapping.

use std::num::Wrapping;

let zero = Wrapping(0u32);
let one = Wrapping(1u32);

assert_eq!(std::u32::MAX, (zero - one).0);

This is a good solution when you want to be explicit about what you’re doing. However, its readability is still not great.

#[wrappit]

To alleviate this shortcoming I implemented a procedural macro that rewrites arithmetic operators +,-,* into their wrapping equivalents wrapping_add, wrapping_sub, wrapping_mul as well as their assigning versions +=,-=,*=.

The following function for example

#[wrappit]
fn mix(a: u32, b: u32, c: &[u32]) -> u32 {
    let mut r = a + b;
    for u in c {
        r *= u;
    }
    r
}

is rewritten to

fn mix(a: u32, b: u32, c: &[u32]) -> u32 {
    let mut r = a.wrapping_add(b);
    for u in c {
        r = r.wrapping_mul(u);
    }
    r
}

You can find wrapping_arithmetic on GitHub and on crates.io. To use #[wrappit] add wrapping_arithmetic = "0.1" to your cargo.toml.

Built with Hugo
Theme Stack designed by Jimmy