RustArena

Step 3 of 7

When numbers overflow

Every integer type has a fixed range. What happens when a calculation goes past it? That's called integer overflow, and in many languages it silently produces a wrong number (a classic source of security bugs).

Rust doesn't let it pass silently:

fn main() {
    let level: u8 = 255;
    let next = level + 1;
    println!("{next}");
}
error: this arithmetic operation will overflow
 --> src/main.rs:3:16
  |
3 |     let next = level + 1;
  |                ^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow

When the values change while the program runs, the compiler can't see the problem, so the debug build checks at run time:

fn main() {
    let mut level: u8 = 250;
    println!("level {level}");
    level += 10;
    println!("level {level}");
}
level 250
thread 'main' panicked at src/main.rs:4:5:
attempt to add with overflow

Choosing what should happen

A panic isn't always what you want, so every integer type has methods that say explicitly how to handle overflow. A method is a function that belongs to a value, called with a dot: value.method(argument).

fn main() {
    let hp: u8 = 250;
    println!("{}", hp.saturating_add(10));
    println!("{}", hp.wrapping_add(10));
    println!("{:?}", hp.checked_add(10));
    println!("{:?}", hp.checked_add(5));
}
255
4
None
Some(255)

There are versions for each operation: _sub, _mul, _div. For unsigned types, saturating_sub stops at 0:

fn main() {
    let stock: u32 = 3;
    println!("{}", stock.saturating_sub(5));
    println!("{:?}", stock.checked_sub(5));
    println!("{:?}", stock.checked_sub(2));
}
0
None
Some(1)

At work

When values come from outside the program (user input, files, the network), a plain + can panic in debug builds or wrap in release builds. Careful code uses checked_ where overflow means bad data and saturating_ where capping is the intended behavior. Often the simplest fix is a big enough type: money in cents as an i64 won't overflow in practice.

Your task

A music player's volume is a u8. Starting from volume = 245, print the volume after turning it up by 20 (it should stop at 255), then print what checked_add says about adding 20:

255
None

Challenge 2

A shop's stock can't go below zero. Fill in the method so selling 7 items from a stock of 4 leaves 0 instead of panicking.

Challenge 3

An 8-bit counter ticks is at 200. Print ticks + 100 three ways, one per line: wrapping, saturating and checked:

44
255
None

Previous: Integer division and remainder Next: Floating-point numbers