Writing slices to a slice?

#1

Given this little example:

Playground

fn main() {
    //given these:
    let srcs:Vec<Vec<f32>> = vec![
        (1..9).map(|v| v as f32).collect(),
        (101..109).map(|v| v as f32).collect()
    ];
    
    let mut dest = [0.0f32; 16];
    
    println!("srcs[0] before: {:?}", srcs[0]);
    println!("srcs[1] before: {:?}", srcs[1]);
    println!("dest before: {:?}", dest);
    
    //write 
    write_slices_to_slice(&srcs, &mut dest);
    
    //it's all there :)
    println!("dest after: {:?}", dest);
}

pub fn write_slices_to_slice<T>(srcs:&[Vec<T>], dest:&mut [T]) 
where T: Copy
{
    let mut offset = 0;
    for src in srcs.iter() {
        for (index, value) in src.iter().enumerate() {
           dest[index + offset] = *value;
        }
        offset += src.len();
    }
}

I have a couple questions:

  1. Is there a simple way to convert a Vec of Vecs to a slice of slices? In other words - I couldn’t figure out an easy way of accepting srcs: &[&[f32]] … in various ways, it seemed the compiler was forcing me to keep the inner type as a Vec.

  2. Is there a way to do the writing itself via combinators instead of the for-loop way?

(let’s assume two different scenarios: one where we know the number of elements in advance, e.g. we’re actually dealing with Arrays all around (both in srcs and dest), and the other - where it comes from a Vec and we don’t know the number of elements)

Thanks!

#2

You can use copy_from_slice

2 Likes
#3

I see… this works

pub fn copy_slices_to_slice<T>(srcs:&[Vec<T>], dest:&mut [T]) 
where T: Copy
{
    let mut offset = 0;
    for src in srcs.iter() {
        let len = src.len();
        let max = offset + len;
        dest[offset..max].copy_from_slice(&src);
        offset = max;
    }
}

Any other tips for improving this are appreciated :slight_smile:

1 Like
#4

If ty our arrays are all less than 32 elements, then you can use AsRef<[T]> instead of Vec<T> to reuse this function for both arrays and Vecs.

pub fn copy_slices_to_slice<T, S>(srcs:&[S], mut dest:&mut [T]) 
where T: Copy,
      S: AsRef<[T]>
{
    for src in srcs.iter() {
        let src = src.as_ref();
        let len = src.len();
        let (copy_to, new_dest) = dest.split_at_mut(len);
        copy_to.copy_from_slice(&src);
        dest = new_dest;
    }
}

Also if you want to allow Clone types, then you can use clone_from_slice

2 Likes
#5

You need [&[f32]] owned by someone else to get &[&[f32]] as it is a reference. You can’t treat [Vec<f32>] as [&[f32]] because they’re completely different types, and even their sizes are different: Vec<f32> is 3 ptr wide and &[f32] is 2 ptr wide. If you want to know more what exactly is &[T], try check my previous post.

1 Like
#6

And for even more generality (you just need the first layer to be an iterable yielding slices):

fn copy_slices_to_slice<'slice, T : Copy + 'slice> (
    slices: impl IntoIterator<Item = &'slice (impl AsRef<[T]> + 'slice)>,
    mut dest: &'_ mut [T],
)
{
    for slice in slices.into_iter().map(AsRef::as_ref) {
        let len = slice.len();
        dest[.. len].copy_from_slice(&slice);
        dest = &mut dest[len ..];
    }
}
2 Likes