How do I get an array (or vec whatever) slice ?!


#1

Hey there,

I’m trying to create a RefCell that contains a fixed size array and then create a slice of it:

let cell = RefCell::new([0u8; 1024]);
let slice = cell.borrow()[0..16];

Compilation fails with the following errors:

refcell.rs:6:6: 6:11 error: the trait `core::marker::Sized` is not implemented for the type `[u8]` [E0277]
refcell.rs:6     let slice = r.borrow()[0..16];
                     ^~~~~
refcell.rs:6:6: 6:11 note: `[u8]` does not have a constant size known at compile-time
refcell.rs:6     let slice = r.borrow()[0..16];
                     ^~~~~
error: aborting due to previous error

Also tried with deref() added before indexing. Looks like the array lost its size…

Then I tried this:

let r = RefCell::new(vec![0u8; 1024]);
let v = r.borrow().deref();
let slice = v[0..16];

No luck here too:

refcell.rs:8:6: 8:11 error: the trait `core::marker::Sized` is not implemented for the type `[u8]` [E0277]
refcell.rs:8     let slice = v[0..16];
                     ^~~~~
refcell.rs:8:6: 8:11 note: `[u8]` does not have a constant size known at compile-time
refcell.rs:8     let slice = v[0..16];
                     ^~~~~
error: aborting due to previous error

The way I see it:
v.borrow() should give me a Ref<Vec<u8>>
v.borrow().deref() should give me a Vec<u8>> which implements Index<Range<usize>>

Obviously I see it wrong… Could someone enlighten me ?

Thanks in advance

B.


#2

This works (type annotations added for clarity):

    let cell = RefCell::new([0u8; 1024]);
    let slice: &[u8] = &cell.borrow()[0..16];

or

    let v = vec![0u8; 1024];
    let slice: &[u8] = &v[0..16];

The & is necessary because the [] operator implicitly dereferences the value returned by the Index::index method, turning it from &[u8] to [u8].

You can’t store a [u8] value in a variable directly because it’s a dynamically-sized type. You can only store a fat pointer to it (type &[u8]).


#3

Thanks !

I don’t get the extra & trick though. The doc of Vec says it implements
Index<Range<usize>> whose Output type is [T] so the index method should return a &[T]
Where does the extra dereference come from ?


#4

The [] operator introduces a deref. v[i] is equivalent to *v.index(i). So a and b here are equivalent:

    let v = vec![1,2,3];
    let a: &[i32] = v.index(0..1);
    let b: &[i32] = &v[0..1];

#5

The process of going from [] syntax to .index() syntax automatically inserts the dereference. v[2] translates to *v.index(2). If it didn’t, and v[2] became v.index(2) where the return type of index was T, then it wouldn’t work to write v[2] = 3, since v[2] would return a copy of the contents at index 2.