I also have v: Vec<u8> of len n*4, guaranteed to be rgba format. Is there a way, without manually looping through every element, to "cast" this Vec<u8> of len n*4 to a Vec<rgba> of len n ?
This can only be done safely if the capacity is a multiple of 4. Generally speaking that's not something you can guarantee unless you use Vec::with_capacity to create it.
Vec does not guarantee any particular growth strategy when reallocating when full, nor when reserve is called. The current strategy is basic and it may prove desirable to use a non-constant growth factor. Whatever strategy is used will of course guarantee O(1) amortized push.
Because rust's current expansion strategy is to double the capacity on overfill, you will seldom run into this issue, but it is still possible:
fn main() {
let mut v = vec![1, 2, 3];
v.push(4);
println!("{}", v.capacity()); // Currently prints 6
}
My crate slice_of_array will allow you to safely convert slices of the vec: This is to say, any owned data you pass around must be Vec<u8>, but you can easily view it as &[Rgba] or &mut [Rgba] at any time.
use slice_of_array::prelude::*;
unsafe impl slice_of_array::IsSliceomorphic for Rgba {
type Element = u8;
const LEN: usize = 4;
}
fn main() {
let v: Vec<u8> = vec![1, 2, 3, 255, 1, 2, 3, 255];
let rgba: &[Rgba] = v.nest(); // panics if len not divisible by 4
assert_eq!(rgba[0], Rgba { r: 1, g: 2, b: 3, a: 255 });
}
In this case, capacity is equal to length, but only because the implementation of stdweb::TypedArray::to_vec uses Vec::with_capacity.
If you want to remain safe, you can do the following:
let slice: Box<[u8]> = vec.into();
let vec: Vec<u8> = slice.into();
The docs of Vec guarantee that this will set cap = len and will only reallocate if necessary. (oddly enough, there is still no such guarantee given for shrink_to_fit(), so stay away from that for now)