Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implicitly grow BytesMut; add BufMutExt::chain_mut #316

Merged
merged 8 commits into from Nov 20, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Expand Up @@ -37,7 +37,7 @@ jobs:
parameters:
name: nightly
# Pin nightly to avoid being impacted by breakage
rust_version: nightly-2019-09-25
rust_version: nightly-2019-11-20
benches: true

# Run tests on some extra platforms
Expand Down
2 changes: 1 addition & 1 deletion src/buf/buf_mut.rs
Expand Up @@ -270,7 +270,7 @@ pub trait BufMut {
fn put_slice(&mut self, src: &[u8]) {
let mut off = 0;

assert!(self.remaining_mut() >= src.len(), "buffer overflow");
assert!(self.remaining_mut() >= src.len(), "buffer overflow; remaining = {}; src = {}", self.remaining_mut(), src.len());

while off < src.len() {
let cnt;
Expand Down
26 changes: 26 additions & 0 deletions src/buf/ext/mod.rs
Expand Up @@ -124,6 +124,32 @@ pub trait BufMutExt: BufMut {
fn writer(self) -> Writer<Self> where Self: Sized {
writer::new(self)
}

/// Creates an adaptor which will chain this buffer with another.
carllerche marked this conversation as resolved.
Show resolved Hide resolved
///
/// The returned `BufMut` instance will first write to all bytes from
/// `self`. Afterwards, it will write to `next`.
///
/// # Examples
///
/// ```
/// use bytes::{BufMut, buf::BufMutExt};
///
/// let mut a = [0u8; 5];
/// let mut b = [0u8; 6];
///
/// let mut chain = (&mut a[..]).chain_mut(&mut b[..]);
///
/// chain.put_slice(b"hello world");
///
/// assert_eq!(&a[..], b"hello");
/// assert_eq!(&b[..], b" world");
/// ```
fn chain_mut<U: BufMut>(self, next: U) -> Chain<Self, U>
where Self: Sized
{
Chain::new(self, next)
}
}

impl<B: BufMut + ?Sized> BufMutExt for B {}
10 changes: 7 additions & 3 deletions src/bytes_mut.rs
Expand Up @@ -924,20 +924,24 @@ impl Buf for BytesMut {
impl BufMut for BytesMut {
#[inline]
fn remaining_mut(&self) -> usize {
self.capacity() - self.len()
usize::MAX - self.len()
}

#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
let new_len = self.len() + cnt;
assert!(new_len <= self.cap);
assert!(new_len <= self.cap, "new_len = {}; capacity = {}", new_len, self.cap);
self.len = new_len;
}

#[inline]
fn bytes_mut(&mut self) -> &mut [mem::MaybeUninit<u8>] {
if self.capacity() == self.len() {
self.reserve(64);
}
carllerche marked this conversation as resolved.
Show resolved Hide resolved

unsafe {
slice::from_raw_parts_mut(self.ptr.as_ptr().offset(self.len as isize) as *mut mem::MaybeUninit<u8>, self.cap)
slice::from_raw_parts_mut(self.ptr.as_ptr().offset(self.len as isize) as *mut mem::MaybeUninit<u8>, self.cap - self.len)
carllerche marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_buf_mut.rs
Expand Up @@ -74,7 +74,7 @@ fn test_bufs_vec_mut() {
// with no capacity
let mut buf = BytesMut::new();
assert_eq!(buf.capacity(), 0);
assert_eq!(0, buf.bytes_vectored_mut(&mut dst[..]));
assert_eq!(1, buf.bytes_vectored_mut(&mut dst[..]));

// with capacity
let mut buf = BytesMut::with_capacity(64);
Expand Down
26 changes: 24 additions & 2 deletions tests/test_bytes.rs
Expand Up @@ -93,8 +93,8 @@ fn fmt_write() {


let mut c = BytesMut::with_capacity(64);
write!(c, "{}", s).unwrap_err();
assert!(c.is_empty());
write!(c, "{}", s).unwrap();
assert_eq!(c, s[..].as_bytes());
}

#[test]
Expand Down Expand Up @@ -820,3 +820,25 @@ fn empty_slice_ref_catches_not_an_empty_subset() {

bytes.slice_ref(slice);
}

#[test]
fn bytes_buf_mut_advance() {
let mut bytes = BytesMut::with_capacity(1024);

unsafe {
let ptr = bytes.bytes_mut().as_ptr();
assert_eq!(1024, bytes.bytes_mut().len());

bytes.advance_mut(10);

let next = bytes.bytes_mut().as_ptr();
assert_eq!(1024 - 10, bytes.bytes_mut().len());
assert_eq!(ptr.offset(10), next);

// advance to the end
bytes.advance_mut(1024 - 10);

// The buffer size is doubled
assert_eq!(1024, bytes.bytes_mut().len());
}
}
13 changes: 5 additions & 8 deletions tests/test_chain.rs
@@ -1,7 +1,7 @@
#![deny(warnings, rust_2018_idioms)]

use bytes::{Buf, BufMut, Bytes, BytesMut};
use bytes::buf::BufExt;
use bytes::{Buf, BufMut, Bytes};
use bytes::buf::{BufExt, BufMutExt};
use std::io::IoSlice;

#[test]
Expand All @@ -15,20 +15,17 @@ fn collect_two_bufs() {

#[test]
fn writing_chained() {
let mut a = BytesMut::with_capacity(64);
let mut b = BytesMut::with_capacity(64);
let mut a = [0u8; 64];
let mut b = [0u8; 64];

{
let mut buf = (&mut a).chain(&mut b);
let mut buf = (&mut a[..]).chain_mut(&mut b[..]);

for i in 0u8..128 {
buf.put_u8(i);
}
}

assert_eq!(64, a.len());
assert_eq!(64, b.len());

for i in 0..64 {
let expect = i as u8;
assert_eq!(expect, a[i]);
Expand Down