Skip to content

Commit 39de065

Browse files
authored
Add Buf::copy_to_bytes(len) (#439)
This method replaces `Buf::to_bytes()`, providing a method that copies a subset of the remaining buffer into a `Bytes` value. As this is strictly more flexible, `to_bytes()` is removed. Fixes: #129, #398
1 parent 5866839 commit 39de065

File tree

6 files changed

+48
-17
lines changed

6 files changed

+48
-17
lines changed

src/buf/buf_impl.rs

+17-9
Original file line numberDiff line numberDiff line change
@@ -795,20 +795,28 @@ pub trait Buf {
795795
f64::from_bits(Self::get_u64_le(self))
796796
}
797797

798-
/// Consumes remaining bytes inside self and returns new instance of `Bytes`
798+
/// Consumes `len` bytes inside self and returns new instance of `Bytes`
799+
/// with this data.
800+
///
801+
/// This function may be optimized by the underlying type to avoid actual
802+
/// copies. For example, `Bytes` implementation will do a shallow copy
803+
/// (ref-count increment).
799804
///
800805
/// # Examples
801806
///
802807
/// ```
803808
/// use bytes::Buf;
804809
///
805-
/// let bytes = (&b"hello world"[..]).to_bytes();
806-
/// assert_eq!(&bytes[..], &b"hello world"[..]);
810+
/// let bytes = (&b"hello world"[..]).copy_to_bytes(5);
811+
/// assert_eq!(&bytes[..], &b"hello"[..]);
807812
/// ```
808-
fn to_bytes(&mut self) -> crate::Bytes {
813+
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
809814
use super::BufMut;
810-
let mut ret = crate::BytesMut::with_capacity(self.remaining());
811-
ret.put(self);
815+
816+
assert!(len <= self.remaining(), "`len` greater than remaining");
817+
818+
let mut ret = crate::BytesMut::with_capacity(len);
819+
ret.put(self.take(len));
812820
ret.freeze()
813821
}
814822

@@ -852,7 +860,7 @@ pub trait Buf {
852860
///
853861
/// let mut chain = b"hello "[..].chain(&b"world"[..]);
854862
///
855-
/// let full = chain.to_bytes();
863+
/// let full = chain.copy_to_bytes(11);
856864
/// assert_eq!(full.bytes(), b"hello world");
857865
/// ```
858866
fn chain<U: Buf>(self, next: U) -> Chain<Self, U>
@@ -993,8 +1001,8 @@ macro_rules! deref_forward_buf {
9931001
(**self).get_int_le(nbytes)
9941002
}
9951003

996-
fn to_bytes(&mut self) -> crate::Bytes {
997-
(**self).to_bytes()
1004+
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
1005+
(**self).copy_to_bytes(len)
9981006
}
9991007
};
10001008
}

src/buf/chain.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use std::io::IoSlice;
2121
/// let mut buf = (&b"hello "[..])
2222
/// .chain(&b"world"[..]);
2323
///
24-
/// let full: Bytes = buf.to_bytes();
24+
/// let full: Bytes = buf.copy_to_bytes(11);
2525
/// assert_eq!(full[..], b"hello world"[..]);
2626
/// ```
2727
///
@@ -68,7 +68,7 @@ impl<T, U> Chain<T, U> {
6868
///
6969
/// buf.first_mut().advance(1);
7070
///
71-
/// let full = buf.to_bytes();
71+
/// let full = buf.copy_to_bytes(9);
7272
/// assert_eq!(full, b"elloworld"[..]);
7373
/// ```
7474
pub fn first_mut(&mut self) -> &mut T {
@@ -103,7 +103,7 @@ impl<T, U> Chain<T, U> {
103103
///
104104
/// buf.last_mut().advance(1);
105105
///
106-
/// let full = buf.to_bytes();
106+
/// let full = buf.copy_to_bytes(10);
107107
/// assert_eq!(full, b"hello orld"[..]);
108108
/// ```
109109
pub fn last_mut(&mut self) -> &mut U {

src/bytes.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,14 @@ impl Buf for Bytes {
548548
}
549549
}
550550

551-
fn to_bytes(&mut self) -> crate::Bytes {
552-
core::mem::replace(self, Bytes::new())
551+
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
552+
if len == self.remaining() {
553+
core::mem::replace(self, Bytes::new())
554+
} else {
555+
let ret = self.slice(..len);
556+
self.advance(len);
557+
ret
558+
}
553559
}
554560
}
555561

src/bytes_mut.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -961,8 +961,8 @@ impl Buf for BytesMut {
961961
}
962962
}
963963

964-
fn to_bytes(&mut self) -> crate::Bytes {
965-
self.split().freeze()
964+
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
965+
self.split_to(len).freeze()
966966
}
967967
}
968968

tests/test_buf.rs

+17
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,20 @@ fn test_deref_buf_forwards() {
101101
assert_eq!((Box::new(Special) as Box<dyn Buf>).get_u8(), b'x');
102102
assert_eq!(Box::new(Special).get_u8(), b'x');
103103
}
104+
105+
#[test]
106+
fn copy_to_bytes_less() {
107+
let mut buf = &b"hello world"[..];
108+
109+
let bytes = buf.copy_to_bytes(5);
110+
assert_eq!(bytes, &b"hello"[..]);
111+
assert_eq!(buf, &b" world"[..])
112+
}
113+
114+
#[test]
115+
#[should_panic]
116+
fn copy_to_bytes_overflow() {
117+
let mut buf = &b"hello world"[..];
118+
119+
let _bytes = buf.copy_to_bytes(12);
120+
}

tests/test_chain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn collect_two_bufs() {
99
let a = Bytes::from(&b"hello"[..]);
1010
let b = Bytes::from(&b"world"[..]);
1111

12-
let res = a.chain(b).to_bytes();
12+
let res = a.chain(b).copy_to_bytes(10);
1313
assert_eq!(res, &b"helloworld"[..]);
1414
}
1515

0 commit comments

Comments
 (0)