pavon
pavon

Reputation: 16589

Rust: Creating a slice from a reference

Is it possible to create a slice of an array (or anything else) using references into that array to specify the start/end rather than indices?

For example, say I am iterating through an array, and when I get to a certain element I want to call a function passing a slice of the array from the current element to the end:

let list = [1, 2, 3, 4, 5, 6];
for item in &list {
   if passes_test(item) {
       process_remainder(&list[item..]); // does not compile
   }
}

Coming from C this seems like a natural thing to want to do - a reference is just a pointer, and a slice is just a pair of pointers (or pointer and length), and taking multiple references should be fine since none of them are mutable. But I can't find right syntax to do it.

Alternately, is it possible to get the index for a given reference (like with pointer arithmetic in C), or do I just need to break down and use enumerate to generate both index and reference as I iterate?

Upvotes: 3

Views: 669

Answers (2)

Thomas
Thomas

Reputation: 182063

You can do it, but it's neither safe nor pretty:

let list = [1, 2, 3, 4, 5, 6];
for item in &list {
    if passes_test(item) {
        let idx = unsafe { (item as *const u64).offset_from(list.as_ptr()) as usize };
        process_remainder(&list[idx..]);
    }
}

Using enumerate is a better option:

let list = [1, 2, 3, 4, 5, 6];
for (i, item) in list.iter().enumerate() {
   if passes_test(item) {
       process_remainder(&list[i..]);
   }
}

Upvotes: 3

aedm
aedm

Reputation: 6614

Usually, enumerate is preferred over pointer arithmetic.

fn main() {
    let list = [1i32, 2, 3, 4, 5, 6];
    for (index, item) in list.iter().enumerate() {
        if *item > 5 {
            process_remainder(&list[index..]);
        }
    }
}

(Accidentally, your code does compile since array items are usize. :) So I changed them to i32.)

Upvotes: 4

Related Questions