3

I have a fixed size buffer in a Bytes struct, and I want to copy some data over the middle of it.

The only thing I can see at the moment would be to take a slice of the beginning, add what I want, and add the slice at the end, but I'm sure this will result in a large copy or two that I want to avoid, I simply need to update the middle of the buffer. Is there a simple way of doing that without using unsafe?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
stu
  • 8,461
  • 18
  • 74
  • 112

1 Answers1

5

You don't mutate Bytes. The entire purpose of the struct is to represent a reference-counted immutable view of data. You will need to copy the data in some fashion. Perhaps you create a Vec<u8> or BytesMut from the data.

BytesMut implements AsMut<[u8]>, BorrowMut<[u8]> and DerefMut, so you can use any existing technique for modifying slices in-place. For example:

use bytes::BytesMut; // 0.5.4

fn main() {
    let mut b = BytesMut::new();
    b.extend_from_slice(b"a good time");

    let middle = &mut b[2..][..4];
    middle.copy_from_slice(b"cool");

    println!("{}", String::from_utf8_lossy(&b));
}

See also:

without using unsafe

Do not use unsafe for this problem. You will cause undefined behavior.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • okay... that's basically what I was looking for thanks, and I know I can't mutate a Bytes, but I'm also not seeing how to gain mutability from a Bytes. And yes, I don't want to use unsafe. – stu May 26 '20 at 19:38
  • 1
    @stu There is `unsafe` and then there is `unsafe`. I mean, there are situations where you *may* use `unsafe`, even though you might not want to, and there are situations where what you want is impossible within the rules of the language and you *must not* use `unsafe` to break them. This is the second kind of situation. If you have a `Bytes`, you cannot mutate it, full stop. You must go back to where the code is giving you the `Bytes` and somehow convince it to give you a `BytesMut` instead. – trent May 26 '20 at 19:55