Using an offset variable to keep track of the next item in a Rust array I am using an offset variable to track the iteration position, and modifying / returning it. Is the below considered bad practice in Rust? I ask this because I don't see dereferencing very often in code I have seen.

fn get_next_u16(input: &amp;[u8], offset: &amp;mut usize) -&gt; u16 {
    let next = ((input[*offset+1] as u16) &lt;&lt; 8) +
                (input[*offset]   as u16);
    *offset += 2;
    next
}

fn main() {
    let input = [1, 2, 3, 4];
    let mut offset = 0;
    let first_u16 = get_next_u16(&amp;input, &amp;mut offset);
    let second_u16 = get_next_u16(&amp;input, &amp;mut offset);
    println!("first: {}", first_u16);
    println!("second: {}", second_u16);
}


The other way I think of doing this is to reassign to the offset variable like:

fn get_next_u16(input: &amp;[u8], offset: usize) -&gt; (usize, u16) {
   (offset+2, ((input[offset+1] as u16) &lt;&lt; 8) +
               (input[offset]   as u16))
}

fn main() {
    let input = [1, 2, 3, 4];
    let offset = 0;
    let (offset, first_u16) = get_next_u16(&amp;input, offset);
    let (offset, second_u16) = get_next_u16(&amp;input, offset);
    println!("first: {}", first_u16);
    println!("second: {}", second_u16);
}


This looks cleaner but now you have to reassign to offset all the time.

Perhaps there is another way to do this also?
Comparing your variants

Your first variant is a C-style variant. In C, we only have one return value, not multiple, so poin&shy;ters are the only way to pass more than a single piece of information to the user. Un&shy;fort&shy;u&shy;na&shy;tely, those pointers sometimes get used in a wrong way, which isn't that easy with Rust. Still the fol&shy;lowing code is somewhat repetitive, isn't it?

let first_u16 = get_next_u16(&amp;input, &amp;mut offset);
let second_u16 = get_next_u16(&amp;input, &amp;mut offset);
let third_u16 = get_next_u16(&amp;input, &amp;mut offset);
let fourth_u16 = get_next_u16(&amp;input, &amp;mut offset);
....
let one_hundred_u16 = get_next_u16(&amp;input, &amp;mut offset);


input and offset are tightly coupled, which shows that there is something amiss. A struct&shy;ured way to handle both at the same time would be great. Or we could search some closure somewhere else.

The latter variant clearly shows the user that there is more information to work with: The usize shouldn't get ignored! After all, it's part of the output. But alas, that's still error prone, since we now can accidentally use the same offset twice:

let (offset2,  first_u16) = get_next_u16(&amp;input, offset);
let (_      , second_u16) = get_next_u16(&amp;input, offset);     // whoops!


That's due to the fact that usize implements the Copy trait.

Iterate with iterators

But let's take a step back: you want a safe way to get the next u16 repeatedly. You want an iterator. Slices already provide a fitting iterator called chunks. Therefore, we can get two u8s easily. All we need to do is to map those chunks:

fn to_u16(input: &amp;[u8]) -&gt; u16 {
    ((input[1] as u16) &lt;&lt; 8) + (input[0] as u16)
}

fn main() {
    let input = [1, 2, 3, 4];
    let output: Vec&lt;_&gt; = input.chunks(2).map(to_u16).collect();
    println!("{:?}", output);
}


Note that this will panic if the input doesn't contain an even number of u8s. You can use the unstable chunks_exact feature or return an Option&lt;u16&gt; instead.

Other remarks

Use rustfmt to format your code. That way your code looks similar to the one written by others.