Repository: tokio-rs/bytes (Rust)

Issue:
BytesMut::freeze ignores advance
Hi,
I created a `BytesBuf` with some data and removed the leading n bytes with `advance(n)`. After some more computations I converted the result to an immutable `Bytes` value. My expectation was that the content of the `BytesMut` and `Bytes` would be identical. Instead the `Bytes` still contained the discared bytes.

Example program:

```rust
use bytes::{BytesMut, Buf, BufMut};

fn main() {
    let mut x = BytesMut::new();
    x.put(&b"hello"[..]);
    
    
    let mut y = BytesMut::new();
    y.put(&b"hello"[..]);
    y.advance(2);

    println!("{:?} {:?}", x, y); // b"hello" b"llo"
    assert_ne!(x, y);
    assert_ne!(&x[..], &y[..]);
    
    let x1 = x.freeze();
    let y1 = y.freeze();
    
    println!("{:?} {:?}", x1, y1); // b"hello" b"hello"
    // expected: b"hello" b"llo"
    assert_eq!(x1, y1);
    assert_eq!(&x1[..], &y1[..]);
}
```

<https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ffaabad67256d03d04f6478d60b93381>

As a work-around I use `split_to` instead of `advance` and ignore the return value.


Discussion:
Oh yea, that seems like a bug in `freeze`. Looking at the source, it seems to grab the original size so it can properly create a `Bytes`, but forgets to advance it forward if need be.



Patch:
diff --git a/src/bytes_mut.rs b/src/bytes_mut.rs
index dc4e4b179..dda5c471e 100644
--- a/src/bytes_mut.rs
+++ b/src/bytes_mut.rs
@@ -233,7 +233,9 @@ impl BytesMut {
                 let (off, _) = self.get_vec_pos();
                 let vec = rebuild_vec(self.ptr.as_ptr(), self.len, self.cap, off);
                 mem::forget(self);
-                vec.into()
+                let mut b: Bytes = vec.into();
+                b.advance(off);
+                b
             }
         } else {
             debug_assert_eq!(self.kind(), KIND_ARC);


Test patch:
diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs
index 40fcae431..47757733c 100644
--- a/tests/test_bytes.rs
+++ b/tests/test_bytes.rs
@@ -342,6 +342,72 @@ fn freeze_clone_unique() {
     assert_eq!(c, s);
 }
 
+#[test]
+fn freeze_after_advance() {
+    let s = &b"abcdefgh"[..];
+    let mut b = BytesMut::from(s);
+    b.advance(1);
+    assert_eq!(b, s[1..]);
+    let b = b.freeze();
+    // Verify fix for #352. Previously, freeze would ignore the start offset
+    // for BytesMuts in Vec mode.
+    assert_eq!(b, s[1..]);
+}
+
+#[test]
+fn freeze_after_advance_arc() {
+    let s = &b"abcdefgh"[..];
+    let mut b = BytesMut::from(s);
+    // Make b Arc
+    let _ = b.split_to(0);
+    b.advance(1);
+    assert_eq!(b, s[1..]);
+    let b = b.freeze();
+    assert_eq!(b, s[1..]);
+}
+
+#[test]
+fn freeze_after_split_to() {
+    let s = &b"abcdefgh"[..];
+    let mut b = BytesMut::from(s);
+    let _ = b.split_to(1);
+    assert_eq!(b, s[1..]);
+    let b = b.freeze();
+    assert_eq!(b, s[1..]);
+}
+
+#[test]
+fn freeze_after_truncate() {
+    let s = &b"abcdefgh"[..];
+    let mut b = BytesMut::from(s);
+    b.truncate(7);
+    assert_eq!(b, s[..7]);
+    let b = b.freeze();
+    assert_eq!(b, s[..7]);
+}
+
+#[test]
+fn freeze_after_truncate_arc() {
+    let s = &b"abcdefgh"[..];
+    let mut b = BytesMut::from(s);
+    // Make b Arc
+    let _ = b.split_to(0);
+    b.truncate(7);
+    assert_eq!(b, s[..7]);
+    let b = b.freeze();
+    assert_eq!(b, s[..7]);
+}
+
+#[test]
+fn freeze_after_split_off() {
+    let s = &b"abcdefgh"[..];
+    let mut b = BytesMut::from(s);
+    let _ = b.split_off(7);
+    assert_eq!(b, s[..7]);
+    let b = b.freeze();
+    assert_eq!(b, s[..7]);
+}
+
 #[test]
 fn fns_defined_for_bytes_mut() {
     let mut bytes = BytesMut::from(&b"hello world"[..]);