As DK. points out, you don’t want wrapping semantics at the integer level:
fn main() {
let idx: usize = 0;
let len = 10;
let next_idx = idx.wrapping_sub(1) % len;
println!("{}", next_idx) // Prints 5!!!
}
Instead, you want to use modulo logic to wrap around:
let next_idx = (idx + len - 1) % len;
This only works if len
+ idx
is less than the max of the type — this is much easier to see with a u8
instead of usize
; just set idx
to 200 and len
to 250.
If you can’t guarantee that the sum of the two values will always be less than the maximum value, I’d probably use the “checked” family of operations. This does the same level of conditional checking you mentioned you already have, but is neatly tied into a single line:
let next_idx = idx.checked_sub(1).unwrap_or(len - 1);