Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I copy a u8 slice into a u32 slice?

When you have two slices of the same type (and length!), Rust provides the copy_from_slice function to copy from one to the other.

But if my source slice is a &[u8] and my target slice is a &[u32], is there any simpler way to copy it than manually iterating? Because there’s no chance of the source values being out of range I thought there might be, but I can’t find one.

fn copy(source: &[u8], target: &mut [u32]) {
    for (i, &ch) in source.iter().enumerate() {
        target[i] = ch as u32;
    }
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

That is about as good as you are going to get. Most of the other solutions are going to require just as much code as this. For example, you could turn it into an iterator chain to try to improve readability. That being said, the original was already quite readable, so this isn’t much of an improvement.

    source
        .iter()
        .copied()
        .map(u32::from)
        .enumerate()
        .for_each(|(index, value)| target[index] = value);

Or as @ChayimFriedman mentioned, you could use itertools‘s set_from. Here is what that would look like:

fn copy(source: &[u8], target: &mut [u32]) {
    target.iter_mut().set_from(source.iter().map(|x| *x as u32));
}

Alternatively, you could also choose to make the function generic. However, at its core it is the same thing so I’m not sure if you really gain any readability from doing this.

fn copy_into_slice_from<A, B>(src: &[A], dst: &mut [B])
where
    A: Copy,
    B: From<A>,
{
    assert_eq!(src.len(), dst.len());

    src.iter()
        .copied()
        .enumerate()
        .for_each(|(index, value)| dst[index] = B::from(value));
}

I suppose another option would be some sort of map_between_slices function to try to save on the amount of code needed while maintaining readability?

/// Ex: map_between_slices(&src, &mut dst, |x| *x as u32);
fn map_between_slices<A, B, F>(src: &[A], dst: &mut [B], mut func: F)
where
    F: for<'a> FnMut(&'a A) -> B,
{
    assert_eq!(src.len(), dst.len());

    src.iter()
        .enumerate()
        .for_each(|(index, value)| dst[index] = func(value));
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading