How to copy slice to Vec<u8>

I'm trying to encode protobuf to Vec without protobuf's encoding method to make more compression and to easy access the required part without deserializing everything.

Looks like my code is not performant as protobuf serialization.

My source code looks like this

buffer.extend(attribute_size.to_be_bytes().iter());

Protobuf library using copy_from_slice
something like this

buffer[bottom..top].copy_from_slice(bytes);

My assumption with extend is that it's iterating the slice and copying one by one instead of copying it in one go.

Is there any idiomatic way to do?
I don't want to track the position and grow (lot of overhead)

is there anyway to make it simple and performant?

Thanks

You have Vec's .extend_from_slice() at your disposal if you want to ensure it boils down to (a potential .reserve(enough) setup call, followed by) a memcpy.

  • In practice, I don't think it will change much, since Vec uses specialization to have .extend() be .extend_from_slice() when the given iterator is a slice::Iter , but this is a brittle / implementation-specific optimization, whereas .extend_from_slice() guarantees it.

how different is that copy_from_slice with extend?

copy_from_slice also iterates and pushes to the vec?

copy_from_slice calls ptr::copy_nonoverlapping, which calls corresponding intrinsic, which should compile down to the (equivalent of) memcpy.

.copy_from_slice() is a method on slices, not necessarily Vecs. It allows overwriting a buffer with a copy from another one. You can use it to write stuff into the already initialized / filled part of a Vec, but that also kind of defeats the purpose of using a Vec to begin with. The main point of a Vec is its being able to grow if / as needed, which .extend_from_slice() does.

  • If you want access to more fine-grained operations on the initialized and non-initialized parts of a Vec, then I recommend you use ::uninit::prelude::VecCapacity utilities:

    use ::uninit::prelude::*;
    
    let buf: &[u8] = attribute_size.to_be_bytes();
    vec.reserve_uninit(buf.len()).copy_from_slice(buf);
    unsafe { vec.set_len(vec.len() + buf.len()); }
    // the previous two lines are equivalent to `.extend_from_slice(buf)`
    
1 Like