Prepend N elements to a slice by using iter::repeat() and chain()

I need to prepend a number elements (prefix) to an existing slice.

My idea was to use iterators for this. Specifically, iter::repeat() and take() to generate the prefix of required length, followed by chain() to append the existing data (slice), and finally collect() to dump the combined data it into a Vec<T>. But I can't get it to work:

fn prepend(data: &[u8], count: usize) -> Vec<u8> {
    std::iter::repeat(0u8).take(count)
        .chain(data.into_iter()).collect::<Vec<u8>>()
}

Error is:

error[E0271]: type mismatch resolving <Iter<'_, u8> as IntoIterator>::Item == u8

Any ideas what is missing here?

&[u8]'s IntoIterator implementation returns an iterator that iterates over &u8, not u8. You need to copy explicitly, i.e.:

fn prepend(data: &[u8], count: usize) -> Vec<u8> {
    std::iter::repeat(0u8).take(count)
        .chain(data.into_iter().copied()).collect::<Vec<u8>>()
}

fn prepend2(data: &[u8], count: usize) -> Vec<u8> {
    std::iter::repeat(0u8).take(count)
        .chain(data.into_iter().map(|x| *x)).collect::<Vec<u8>>()
}

are both possible solutions to copy the bytes from data into the new vector (using copied is more readable than the implicit copy that happens when we return the dereferenced byte from the closure we pass to map in the prepend2 IMO). Playground.

1 Like

&[u8]'s IntoIterator implementation returns an iterator that iterates over &u8, not u8

Now I see! Thanks for pointing me at the copied() function :sunglasses:

If there is a lifetime involved when you don't expect one, you can bet something is a reference when you think it's a value. The compiler mentions the item type explicitly, which you can then look up in the documentation.

1 Like

Note - if you're doing a lot of these prepend operations, you might want to use a VecDeque for O(1) prepend operations.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.