Skip to content

Commit b8e9325

Browse files
stepancheglelongg
authored andcommitted
BufMut::put_bytes(self, val, cnt) (tokio-rs#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 80e5fe2 commit b8e9325

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
@@ -262,6 +262,37 @@ pub unsafe trait BufMut {
262262
}
263263
}
264264

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

10341073
#[cfg(feature = "alloc")]
@@ -1094,6 +1133,11 @@ unsafe impl BufMut for Vec<u8> {
10941133
fn put_slice(&mut self, src: &[u8]) {
10951134
self.extend_from_slice(src);
10961135
}
1136+
1137+
fn put_bytes(&mut self, val: u8, cnt: usize) {
1138+
let new_len = self.len().checked_add(cnt).unwrap();
1139+
self.resize(new_len, val);
1140+
}
10971141
}
10981142

10991143
// 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
@@ -28,6 +28,14 @@ fn test_vec_as_mut_buf() {
2828
assert_eq!(buf.len(), 68);
2929
}
3030

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

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

tests/test_bytes.rs

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

0 commit comments

Comments
 (0)