Skip to content

Commit ef7f257

Browse files
authored
Specialize BytesMut::put::<Bytes> (#793)
1 parent 8b4f54d commit ef7f257

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/bytes_mut.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,11 +1201,21 @@ unsafe impl BufMut for BytesMut {
12011201
where
12021202
Self: Sized,
12031203
{
1204-
while src.has_remaining() {
1205-
let s = src.chunk();
1206-
let l = s.len();
1207-
self.extend_from_slice(s);
1208-
src.advance(l);
1204+
// When capacity is zero, try reusing allocation of `src`.
1205+
if self.capacity() == 0 {
1206+
let src_copy = src.copy_to_bytes(src.remaining());
1207+
drop(src);
1208+
match src_copy.try_into_mut() {
1209+
Ok(bytes_mut) => *self = bytes_mut,
1210+
Err(bytes) => self.extend_from_slice(&bytes),
1211+
}
1212+
} else {
1213+
while src.has_remaining() {
1214+
let s = src.chunk();
1215+
let l = s.len();
1216+
self.extend_from_slice(s);
1217+
src.advance(l);
1218+
}
12091219
}
12101220
}
12111221

tests/test_bytes.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,3 +1688,22 @@ fn owned_safe_drop_on_as_ref_panic() {
16881688
assert!(result.is_err());
16891689
assert_eq!(drop_counter.get(), 1);
16901690
}
1691+
1692+
/// Test `BytesMut::put` reuses allocation of `Bytes`.
1693+
#[test]
1694+
fn bytes_mut_put_bytes_specialization() {
1695+
let mut vec = Vec::with_capacity(1234);
1696+
vec.push(10);
1697+
let capacity = vec.capacity();
1698+
assert!(capacity >= 1234);
1699+
1700+
// Make `Bytes` backed by `Vec`.
1701+
let bytes = Bytes::from(vec);
1702+
let mut bytes_mut = BytesMut::new();
1703+
bytes_mut.put(bytes);
1704+
1705+
// Check contents is correct.
1706+
assert_eq!(&[10], bytes_mut.as_ref());
1707+
// If allocation is reused, capacity should be equal to original vec capacity.
1708+
assert_eq!(bytes_mut.capacity(), capacity);
1709+
}

0 commit comments

Comments
 (0)