Skip to content

Commit 2697fa7

Browse files
authored
BufMut::put_bytes(self, val, cnt) (#487)
Equivalent to ``` for _ in 0..cnt { self.put_u8(val); } ``` but may work faster. Name and signature is chosen to be consistent with `ptr::write_bytes`. Include three specializations: * `Vec<u8>` * `&mut [u8]` * `BytesMut` `BytesMut` and `&mut [u8]` specializations use `ptr::write`, `Vec<u8>` specialization uses `Vec::resize`.
1 parent fa9cbf1 commit 2697fa7

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

src/buf/buf_mut.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,37 @@ pub unsafe trait BufMut {
261261
}
262262
}
263263

264+
/// Put `cnt` bytes `val` into `self`.
265+
///
266+
/// Logically equivalent to calling `self.put_u8(val)` `cnt` times, but may work faster.
267+
///
268+
/// `self` must have at least `cnt` remaining capacity.
269+
///
270+
/// ```
271+
/// use bytes::BufMut;
272+
///
273+
/// let mut dst = [0; 6];
274+
///
275+
/// {
276+
/// let mut buf = &mut dst[..];
277+
/// buf.put_bytes(b'a', 4);
278+
///
279+
/// assert_eq!(2, buf.remaining_mut());
280+
/// }
281+
///
282+
/// assert_eq!(b"aaaa\0\0", &dst);
283+
/// ```
284+
///
285+
/// # Panics
286+
///
287+
/// This function panics if there is not enough remaining capacity in
288+
/// `self`.
289+
fn put_bytes(&mut self, val: u8, cnt: usize) {
290+
for _ in 0..cnt {
291+
self.put_u8(val);
292+
}
293+
}
294+
264295
/// Writes an unsigned 8 bit integer to `self`.
265296
///
266297
/// The current position is advanced by 1.
@@ -1027,6 +1058,14 @@ unsafe impl BufMut for &mut [u8] {
10271058
self.advance_mut(src.len());
10281059
}
10291060
}
1061+
1062+
fn put_bytes(&mut self, val: u8, cnt: usize) {
1063+
assert!(self.remaining_mut() >= cnt);
1064+
unsafe {
1065+
ptr::write_bytes(self.as_mut_ptr(), val, cnt);
1066+
self.advance_mut(cnt);
1067+
}
1068+
}
10301069
}
10311070

10321071
unsafe impl BufMut for Vec<u8> {
@@ -1091,6 +1130,11 @@ unsafe impl BufMut for Vec<u8> {
10911130
fn put_slice(&mut self, src: &[u8]) {
10921131
self.extend_from_slice(src);
10931132
}
1133+
1134+
fn put_bytes(&mut self, val: u8, cnt: usize) {
1135+
let new_len = self.len().checked_add(cnt).unwrap();
1136+
self.resize(new_len, val);
1137+
}
10941138
}
10951139

10961140
// The existence of this function makes the compiler catch if the BufMut

src/bytes_mut.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,19 @@ unsafe impl BufMut for BytesMut {
10101010
fn put_slice(&mut self, src: &[u8]) {
10111011
self.extend_from_slice(src);
10121012
}
1013+
1014+
fn put_bytes(&mut self, val: u8, cnt: usize) {
1015+
self.reserve(cnt);
1016+
unsafe {
1017+
let dst = self.uninit_slice();
1018+
// Reserved above
1019+
debug_assert!(dst.len() >= cnt);
1020+
1021+
ptr::write_bytes(dst.as_mut_ptr(), val, cnt);
1022+
1023+
self.advance_mut(cnt);
1024+
}
1025+
}
10131026
}
10141027

10151028
impl AsRef<[u8]> for BytesMut {

tests/test_buf_mut.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ fn test_vec_as_mut_buf() {
2727
assert_eq!(buf.len(), 68);
2828
}
2929

30+
#[test]
31+
fn test_vec_put_bytes() {
32+
let mut buf = Vec::new();
33+
buf.push(17);
34+
buf.put_bytes(19, 2);
35+
assert_eq!([17, 19, 19], &buf[..]);
36+
}
37+
3038
#[test]
3139
fn test_put_u8() {
3240
let mut buf = Vec::with_capacity(8);
@@ -103,6 +111,16 @@ fn test_mut_slice() {
103111
assert_eq!(&v, &[0, 0, 0, 42]);
104112
}
105113

114+
#[test]
115+
fn test_slice_put_bytes() {
116+
let mut v = [0, 0, 0, 0];
117+
let mut s = &mut v[..];
118+
s.put_u8(17);
119+
s.put_bytes(19, 2);
120+
assert_eq!(1, s.remaining_mut());
121+
assert_eq!(&[17, 19, 19, 0], &v[..]);
122+
}
123+
106124
#[test]
107125
fn test_deref_bufmut_forwards() {
108126
struct Special;

tests/test_bytes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -986,3 +986,11 @@ fn bytes_with_capacity_but_empty() {
986986
let vec = Vec::with_capacity(1);
987987
let _ = Bytes::from(vec);
988988
}
989+
990+
#[test]
991+
fn bytes_put_bytes() {
992+
let mut bytes = BytesMut::new();
993+
bytes.put_u8(17);
994+
bytes.put_bytes(19, 2);
995+
assert_eq!([17, 19, 19], bytes.as_ref());
996+
}

0 commit comments

Comments
 (0)