mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-27 00:00:17 +02:00
Implement BufMut for &mut [MaybeUninit<u8>] (#597)
This commit is contained in:
@@ -1419,6 +1419,41 @@ unsafe impl BufMut for &mut [u8] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl BufMut for &mut [core::mem::MaybeUninit<u8>] {
|
||||||
|
#[inline]
|
||||||
|
fn remaining_mut(&self) -> usize {
|
||||||
|
self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn chunk_mut(&mut self) -> &mut UninitSlice {
|
||||||
|
UninitSlice::from_uninit_slice(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn advance_mut(&mut self, cnt: usize) {
|
||||||
|
// Lifetime dance taken from `impl Write for &mut [u8]`.
|
||||||
|
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
|
||||||
|
*self = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn put_slice(&mut self, src: &[u8]) {
|
||||||
|
self.chunk_mut()[..src.len()].copy_from_slice(src);
|
||||||
|
unsafe {
|
||||||
|
self.advance_mut(src.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn put_bytes(&mut self, val: u8, cnt: usize) {
|
||||||
|
assert!(self.remaining_mut() >= cnt);
|
||||||
|
unsafe {
|
||||||
|
ptr::write_bytes(self.as_mut_ptr() as *mut u8, val, cnt);
|
||||||
|
self.advance_mut(cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl BufMut for Vec<u8> {
|
unsafe impl BufMut for Vec<u8> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn remaining_mut(&self) -> usize {
|
fn remaining_mut(&self) -> usize {
|
||||||
|
|||||||
+111
-14
@@ -3,6 +3,7 @@
|
|||||||
use bytes::buf::UninitSlice;
|
use bytes::buf::UninitSlice;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
use core::usize;
|
use core::usize;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -101,24 +102,120 @@ fn test_clone() {
|
|||||||
assert!(buf != buf2);
|
assert!(buf != buf2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
fn do_test_slice_small<T: ?Sized>(make: impl Fn(&mut [u8]) -> &mut T)
|
||||||
fn test_mut_slice() {
|
where
|
||||||
let mut v = vec![0, 0, 0, 0];
|
for<'r> &'r mut T: BufMut,
|
||||||
let mut s = &mut v[..];
|
{
|
||||||
s.put_u32(42);
|
let mut buf = [b'X'; 8];
|
||||||
|
|
||||||
assert_eq!(s.len(), 0);
|
let mut slice = make(&mut buf[..]);
|
||||||
assert_eq!(&v, &[0, 0, 0, 42]);
|
slice.put_bytes(b'A', 2);
|
||||||
|
slice.put_u8(b'B');
|
||||||
|
slice.put_slice(b"BCC");
|
||||||
|
assert_eq!(2, slice.remaining_mut());
|
||||||
|
assert_eq!(b"AABBCCXX", &buf[..]);
|
||||||
|
|
||||||
|
let mut slice = make(&mut buf[..]);
|
||||||
|
slice.put_u32(0x61626364);
|
||||||
|
assert_eq!(4, slice.remaining_mut());
|
||||||
|
assert_eq!(b"abcdCCXX", &buf[..]);
|
||||||
|
|
||||||
|
let mut slice = make(&mut buf[..]);
|
||||||
|
slice.put_u32_le(0x30313233);
|
||||||
|
assert_eq!(4, slice.remaining_mut());
|
||||||
|
assert_eq!(b"3210CCXX", &buf[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_test_slice_large<T: ?Sized>(make: impl Fn(&mut [u8]) -> &mut T)
|
||||||
|
where
|
||||||
|
for<'r> &'r mut T: BufMut,
|
||||||
|
{
|
||||||
|
const LEN: usize = 100;
|
||||||
|
const FILL: [u8; LEN] = [b'Y'; LEN];
|
||||||
|
|
||||||
|
let test = |fill: &dyn Fn(&mut &mut T, usize)| {
|
||||||
|
for buf_len in 0..LEN {
|
||||||
|
let mut buf = [b'X'; LEN];
|
||||||
|
for fill_len in 0..=buf_len {
|
||||||
|
let mut slice = make(&mut buf[..buf_len]);
|
||||||
|
fill(&mut slice, fill_len);
|
||||||
|
assert_eq!(buf_len - fill_len, slice.remaining_mut());
|
||||||
|
let (head, tail) = buf.split_at(fill_len);
|
||||||
|
assert_eq!(&FILL[..fill_len], head);
|
||||||
|
assert!(tail.iter().all(|b| *b == b'X'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test(&|slice, fill_len| slice.put_slice(&FILL[..fill_len]));
|
||||||
|
test(&|slice, fill_len| slice.put_bytes(FILL[0], fill_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_test_slice_put_slice_panics<T: ?Sized>(make: impl Fn(&mut [u8]) -> &mut T)
|
||||||
|
where
|
||||||
|
for<'r> &'r mut T: BufMut,
|
||||||
|
{
|
||||||
|
let mut buf = [b'X'; 4];
|
||||||
|
let mut slice = make(&mut buf[..]);
|
||||||
|
slice.put_slice(b"12345");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_test_slice_put_bytes_panics<T: ?Sized>(make: impl Fn(&mut [u8]) -> &mut T)
|
||||||
|
where
|
||||||
|
for<'r> &'r mut T: BufMut,
|
||||||
|
{
|
||||||
|
let mut buf = [b'X'; 4];
|
||||||
|
let mut slice = make(&mut buf[..]);
|
||||||
|
slice.put_bytes(b'1', 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_put_bytes() {
|
fn test_slice_buf_mut_small() {
|
||||||
let mut v = [0, 0, 0, 0];
|
do_test_slice_small(|x| x);
|
||||||
let mut s = &mut v[..];
|
}
|
||||||
s.put_u8(17);
|
|
||||||
s.put_bytes(19, 2);
|
#[test]
|
||||||
assert_eq!(1, s.remaining_mut());
|
fn test_slice_buf_mut_large() {
|
||||||
assert_eq!(&[17, 19, 19, 0], &v[..]);
|
do_test_slice_large(|x| x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_slice_buf_mut_put_slice_overflow() {
|
||||||
|
do_test_slice_put_slice_panics(|x| x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_slice_buf_mut_put_bytes_overflow() {
|
||||||
|
do_test_slice_put_bytes_panics(|x| x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_maybe_uninit_slice(slice: &mut [u8]) -> &mut [MaybeUninit<u8>] {
|
||||||
|
// SAFETY: [u8] has the same layout as [MaybeUninit<u8>].
|
||||||
|
unsafe { core::mem::transmute(slice) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_maybe_uninit_buf_mut_small() {
|
||||||
|
do_test_slice_small(make_maybe_uninit_slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_maybe_uninit_buf_mut_large() {
|
||||||
|
do_test_slice_large(make_maybe_uninit_slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_maybe_uninit_buf_mut_put_slice_overflow() {
|
||||||
|
do_test_slice_put_slice_panics(make_maybe_uninit_slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn test_maybe_uninit_buf_mut_put_bytes_overflow() {
|
||||||
|
do_test_slice_put_bytes_panics(make_maybe_uninit_slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user