We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ground Rules: Values, Types, Control Flow step 5 of 24
Wrap an eight-bit meter reading
Implement an eight-bit meter that wraps through the values 0..=255:
pub fn meter_readings(start: u8, deltas: &[i32]) -> Vec<u8>
Apply each signed delta to the current reading and return the reading after
every update. Do not include the starting reading. Empty deltas gives an
empty vector. Support the full i32 range, including negative deltas and
changes larger than one revolution.
For start = 250 and deltas = [10, -20, 300]:
| Current reading | Delta | Mathematical sum | Next reading |
|---|---|---|---|
| 250 | 10 | 260 | 4 |
| 4 | -20 | -16 | 240 |
| 240 | 300 | 540 | 28 |
The result is [4, 240, 28]. Each next reading is the mathematical sum
modulo 256, expressed as a value from 0 through 255. A delta of 256 or -256
leaves the reading unchanged.
Fix the type mismatch
The starter's current += d mixes u8 and i32. Rust does not implicitly
convert one integer operand to match the other, so that statement fails to
compile.
For this task, d as u8 is useful: it keeps the lowest eight bits. For example:
| Delta | d as u8 |
|---|---|
| 10 | 10 |
| -20 | 236 |
| 300 | 44 |
| 256 | 0 |
This is a truncating conversion, not a range check. It suits this meter because adding the truncated delta modulo 256 has the same result as adding the original delta modulo 256. For data that must fit without losing information, a checked conversion would be a different requirement.
Make wrapping explicit
Use wrapping_add to combine the current reading and the converted delta.
It returns the wrapped result regardless of whether overflow checks are on.
The cast does not overflow; the subsequent addition is the operation that
needs an explicit wrapping policy.
Avoid computing i32::from(current) + d first: that intermediate sum can
overflow when d is near i32::MAX. Converting the delta to a byte and
using wrapping addition avoids that intermediate calculation.
Why ordinary addition can behave differently
For runtime integer addition, default debug builds check overflow and panic;
default release builds disable those checks and wrap. These are defaults,
not requirements of optimization itself. Cargo's overflow-checks setting
and rustc's -C overflow-checks option can change the behavior independently
of optimization level.
The site's current Rust runner uses rustc -O. Plain += can therefore
produce the expected readings there while panicking in a local debug build.
Explicit wrapping makes the function's behavior follow its contract in both.
Do not generalize this to every operation: integer division by zero still panics at runtime in optimized builds, for example.
Compile-time diagnostics are a separate check
This ordinary statement is rejected by rustc's default arithmetic_overflow
lint because the overflow is apparent without running the code:
let x: u8 = 250 + 10;
A required constant expression such as const X: u8 = 250 + 10; also fails
constant evaluation. That is distinct from a lint on an ordinary statement:
allowing the lint does not make the invalid constant valid.
Intentional constant wrapping is valid when expressed explicitly:
const X: u8 = 250u8.wrapping_add(10);
assert_eq!(X, 4);
Choose arithmetic that expresses the intended behavior. This meter wraps; a different task might need checked or saturating arithmetic instead.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.