Various cleanup (#635)

This commit is contained in:
Alice Ryhl
2023-10-02 15:40:02 +02:00
committed by GitHub
parent a4e16a552b
commit fd9243f9e2
8 changed files with 351 additions and 137 deletions
+187 -74
View File
@@ -1,8 +1,9 @@
use crate::buf::{limit, Chain, Limit, UninitSlice};
#[cfg(feature = "std")]
use crate::buf::{writer, Writer};
use crate::{panic_advance, panic_does_not_fit};
use core::{cmp, mem, ptr, usize};
use core::{mem, ptr, usize};
use alloc::{boxed::Box, vec::Vec};
@@ -67,8 +68,10 @@ pub unsafe trait BufMut {
/// The next call to `chunk_mut` will return a slice starting `cnt` bytes
/// further into the underlying buffer.
///
/// This function is unsafe because there is no guarantee that the bytes
/// being advanced past have been initialized.
/// # Safety
///
/// The caller must ensure that the next `cnt` bytes of `chunk` are
/// initialized.
///
/// # Examples
///
@@ -121,6 +124,7 @@ pub unsafe trait BufMut {
///
/// assert!(!buf.has_remaining_mut());
/// ```
#[inline]
fn has_remaining_mut(&self) -> bool {
self.remaining_mut() > 0
}
@@ -194,27 +198,25 @@ pub unsafe trait BufMut {
/// # Panics
///
/// Panics if `self` does not have enough capacity to contain `src`.
#[inline]
fn put<T: super::Buf>(&mut self, mut src: T)
where
Self: Sized,
{
assert!(self.remaining_mut() >= src.remaining());
if self.remaining_mut() < src.remaining() {
panic_advance(src.remaining(), self.remaining_mut());
}
while src.has_remaining() {
let l;
let s = src.chunk();
let d = self.chunk_mut();
let cnt = usize::min(s.len(), d.len());
unsafe {
let s = src.chunk();
let d = self.chunk_mut();
l = cmp::min(s.len(), d.len());
d[..cnt].copy_from_slice(&s[..cnt]);
ptr::copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr() as *mut u8, l);
}
src.advance(l);
unsafe {
self.advance_mut(l);
}
// SAFETY: We just initialized `cnt` bytes in `self`.
unsafe { self.advance_mut(cnt) };
src.advance(cnt);
}
}
@@ -237,31 +239,21 @@ pub unsafe trait BufMut {
///
/// assert_eq!(b"hello\0", &dst);
/// ```
fn put_slice(&mut self, src: &[u8]) {
let mut off = 0;
#[inline]
fn put_slice(&mut self, mut src: &[u8]) {
if self.remaining_mut() < src.len() {
panic_advance(src.len(), self.remaining_mut());
}
assert!(
self.remaining_mut() >= src.len(),
"buffer overflow; remaining = {}; src = {}",
self.remaining_mut(),
src.len()
);
while !src.is_empty() {
let dst = self.chunk_mut();
let cnt = usize::min(src.len(), dst.len());
while off < src.len() {
let cnt;
dst[..cnt].copy_from_slice(&src[..cnt]);
src = &src[cnt..];
unsafe {
let dst = self.chunk_mut();
cnt = cmp::min(dst.len(), src.len() - off);
ptr::copy_nonoverlapping(src[off..].as_ptr(), dst.as_mut_ptr() as *mut u8, cnt);
off += cnt;
}
unsafe {
self.advance_mut(cnt);
}
// SAFETY: We just initialized `cnt` bytes in `self`.
unsafe { self.advance_mut(cnt) };
}
}
@@ -290,9 +282,20 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
fn put_bytes(&mut self, val: u8, cnt: usize) {
for _ in 0..cnt {
self.put_u8(val);
#[inline]
fn put_bytes(&mut self, val: u8, mut cnt: usize) {
if self.remaining_mut() < cnt {
panic_advance(cnt, self.remaining_mut());
}
while cnt > 0 {
let dst = self.chunk_mut();
let dst_len = usize::min(dst.len(), cnt);
// SAFETY: The pointer is valid for `dst_len <= dst.len()` bytes.
unsafe { core::ptr::write_bytes(dst.as_mut_ptr(), val, dst_len) };
// SAFETY: We just initialized `dst_len` bytes in `self`.
unsafe { self.advance_mut(dst_len) };
cnt -= dst_len;
}
}
@@ -314,6 +317,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u8(&mut self, n: u8) {
let src = [n];
self.put_slice(&src);
@@ -337,6 +341,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i8(&mut self, n: i8) {
let src = [n as u8];
self.put_slice(&src)
@@ -360,6 +365,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u16(&mut self, n: u16) {
self.put_slice(&n.to_be_bytes())
}
@@ -382,6 +388,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u16_le(&mut self, n: u16) {
self.put_slice(&n.to_le_bytes())
}
@@ -408,6 +415,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u16_ne(&mut self, n: u16) {
self.put_slice(&n.to_ne_bytes())
}
@@ -430,6 +438,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i16(&mut self, n: i16) {
self.put_slice(&n.to_be_bytes())
}
@@ -452,6 +461,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i16_le(&mut self, n: i16) {
self.put_slice(&n.to_le_bytes())
}
@@ -478,6 +488,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i16_ne(&mut self, n: i16) {
self.put_slice(&n.to_ne_bytes())
}
@@ -500,6 +511,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u32(&mut self, n: u32) {
self.put_slice(&n.to_be_bytes())
}
@@ -522,6 +534,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u32_le(&mut self, n: u32) {
self.put_slice(&n.to_le_bytes())
}
@@ -548,6 +561,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u32_ne(&mut self, n: u32) {
self.put_slice(&n.to_ne_bytes())
}
@@ -570,6 +584,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i32(&mut self, n: i32) {
self.put_slice(&n.to_be_bytes())
}
@@ -592,6 +607,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i32_le(&mut self, n: i32) {
self.put_slice(&n.to_le_bytes())
}
@@ -618,6 +634,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i32_ne(&mut self, n: i32) {
self.put_slice(&n.to_ne_bytes())
}
@@ -640,6 +657,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u64(&mut self, n: u64) {
self.put_slice(&n.to_be_bytes())
}
@@ -662,6 +680,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u64_le(&mut self, n: u64) {
self.put_slice(&n.to_le_bytes())
}
@@ -688,6 +707,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u64_ne(&mut self, n: u64) {
self.put_slice(&n.to_ne_bytes())
}
@@ -710,6 +730,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i64(&mut self, n: i64) {
self.put_slice(&n.to_be_bytes())
}
@@ -732,6 +753,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i64_le(&mut self, n: i64) {
self.put_slice(&n.to_le_bytes())
}
@@ -758,6 +780,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i64_ne(&mut self, n: i64) {
self.put_slice(&n.to_ne_bytes())
}
@@ -780,6 +803,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u128(&mut self, n: u128) {
self.put_slice(&n.to_be_bytes())
}
@@ -802,6 +826,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u128_le(&mut self, n: u128) {
self.put_slice(&n.to_le_bytes())
}
@@ -828,6 +853,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_u128_ne(&mut self, n: u128) {
self.put_slice(&n.to_ne_bytes())
}
@@ -850,6 +876,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i128(&mut self, n: i128) {
self.put_slice(&n.to_be_bytes())
}
@@ -872,6 +899,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i128_le(&mut self, n: i128) {
self.put_slice(&n.to_le_bytes())
}
@@ -898,6 +926,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_i128_ne(&mut self, n: i128) {
self.put_slice(&n.to_ne_bytes())
}
@@ -919,9 +948,15 @@ pub unsafe trait BufMut {
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
/// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_uint(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
let start = match mem::size_of_val(&n).checked_sub(nbytes) {
Some(start) => start,
None => panic_does_not_fit(nbytes, mem::size_of_val(&n)),
};
self.put_slice(&n.to_be_bytes()[start..]);
}
/// Writes an unsigned n-byte integer to `self` in the little-endian byte order.
@@ -941,9 +976,16 @@ pub unsafe trait BufMut {
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
/// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_uint_le(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
let slice = n.to_le_bytes();
let slice = match slice.get(..nbytes) {
Some(slice) => slice,
None => panic_does_not_fit(nbytes, slice.len()),
};
self.put_slice(slice);
}
/// Writes an unsigned n-byte integer to `self` in the native-endian byte order.
@@ -967,7 +1009,8 @@ pub unsafe trait BufMut {
/// # Panics
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
/// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_uint_ne(&mut self, n: u64, nbytes: usize) {
if cfg!(target_endian = "big") {
self.put_uint(n, nbytes)
@@ -994,8 +1037,14 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_int(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
let start = match mem::size_of_val(&n).checked_sub(nbytes) {
Some(start) => start,
None => panic_does_not_fit(nbytes, mem::size_of_val(&n)),
};
self.put_slice(&n.to_be_bytes()[start..]);
}
/// Writes low `nbytes` of a signed integer to `self` in little-endian byte order.
@@ -1016,8 +1065,15 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_int_le(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
let slice = n.to_le_bytes();
let slice = match slice.get(..nbytes) {
Some(slice) => slice,
None => panic_does_not_fit(nbytes, slice.len()),
};
self.put_slice(slice);
}
/// Writes low `nbytes` of a signed integer to `self` in native-endian byte order.
@@ -1042,6 +1098,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_int_ne(&mut self, n: i64, nbytes: usize) {
if cfg!(target_endian = "big") {
self.put_int(n, nbytes)
@@ -1069,6 +1126,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_f32(&mut self, n: f32) {
self.put_u32(n.to_bits());
}
@@ -1092,6 +1150,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_f32_le(&mut self, n: f32) {
self.put_u32_le(n.to_bits());
}
@@ -1119,6 +1178,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_f32_ne(&mut self, n: f32) {
self.put_u32_ne(n.to_bits());
}
@@ -1142,6 +1202,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_f64(&mut self, n: f64) {
self.put_u64(n.to_bits());
}
@@ -1165,6 +1226,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_f64_le(&mut self, n: f64) {
self.put_u64_le(n.to_bits());
}
@@ -1192,6 +1254,7 @@ pub unsafe trait BufMut {
///
/// This function panics if there is not enough remaining capacity in
/// `self`.
#[inline]
fn put_f64_ne(&mut self, n: f64) {
self.put_u64_ne(n.to_bits());
}
@@ -1209,6 +1272,7 @@ pub unsafe trait BufMut {
/// let dst = arr.limit(10);
/// assert_eq!(dst.remaining_mut(), 10);
/// ```
#[inline]
fn limit(self, limit: usize) -> Limit<Self>
where
Self: Sized,
@@ -1240,6 +1304,7 @@ pub unsafe trait BufMut {
/// ```
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[inline]
fn writer(self) -> Writer<Self>
where
Self: Sized,
@@ -1267,6 +1332,7 @@ pub unsafe trait BufMut {
/// assert_eq!(&a[..], b"hello");
/// assert_eq!(&b[..], b" world");
/// ```
#[inline]
fn chain_mut<U: BufMut>(self, next: U) -> Chain<Self, U>
where
Self: Sized,
@@ -1277,98 +1343,122 @@ pub unsafe trait BufMut {
macro_rules! deref_forward_bufmut {
() => {
#[inline]
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice {
(**self).chunk_mut()
}
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt)
}
#[inline]
fn put_slice(&mut self, src: &[u8]) {
(**self).put_slice(src)
}
#[inline]
fn put_u8(&mut self, n: u8) {
(**self).put_u8(n)
}
#[inline]
fn put_i8(&mut self, n: i8) {
(**self).put_i8(n)
}
#[inline]
fn put_u16(&mut self, n: u16) {
(**self).put_u16(n)
}
#[inline]
fn put_u16_le(&mut self, n: u16) {
(**self).put_u16_le(n)
}
#[inline]
fn put_u16_ne(&mut self, n: u16) {
(**self).put_u16_ne(n)
}
#[inline]
fn put_i16(&mut self, n: i16) {
(**self).put_i16(n)
}
#[inline]
fn put_i16_le(&mut self, n: i16) {
(**self).put_i16_le(n)
}
#[inline]
fn put_i16_ne(&mut self, n: i16) {
(**self).put_i16_ne(n)
}
#[inline]
fn put_u32(&mut self, n: u32) {
(**self).put_u32(n)
}
#[inline]
fn put_u32_le(&mut self, n: u32) {
(**self).put_u32_le(n)
}
#[inline]
fn put_u32_ne(&mut self, n: u32) {
(**self).put_u32_ne(n)
}
#[inline]
fn put_i32(&mut self, n: i32) {
(**self).put_i32(n)
}
#[inline]
fn put_i32_le(&mut self, n: i32) {
(**self).put_i32_le(n)
}
#[inline]
fn put_i32_ne(&mut self, n: i32) {
(**self).put_i32_ne(n)
}
#[inline]
fn put_u64(&mut self, n: u64) {
(**self).put_u64(n)
}
#[inline]
fn put_u64_le(&mut self, n: u64) {
(**self).put_u64_le(n)
}
#[inline]
fn put_u64_ne(&mut self, n: u64) {
(**self).put_u64_ne(n)
}
#[inline]
fn put_i64(&mut self, n: i64) {
(**self).put_i64(n)
}
#[inline]
fn put_i64_le(&mut self, n: i64) {
(**self).put_i64_le(n)
}
#[inline]
fn put_i64_ne(&mut self, n: i64) {
(**self).put_i64_ne(n)
}
@@ -1391,12 +1481,15 @@ unsafe impl BufMut for &mut [u8] {
#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice {
// UninitSlice is repr(transparent), so safe to transmute
unsafe { &mut *(*self as *mut [u8] as *mut _) }
UninitSlice::new(self)
}
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
if self.len() < cnt {
panic_advance(cnt, self.len());
}
// Lifetime dance taken from `impl Write for &mut [u8]`.
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b;
@@ -1404,14 +1497,22 @@ unsafe impl BufMut for &mut [u8] {
#[inline]
fn put_slice(&mut self, src: &[u8]) {
self[..src.len()].copy_from_slice(src);
unsafe {
self.advance_mut(src.len());
if self.len() < src.len() {
panic_advance(src.len(), self.len());
}
self[..src.len()].copy_from_slice(src);
// SAFETY: We just initialized `src.len()` bytes.
unsafe { self.advance_mut(src.len()) };
}
#[inline]
fn put_bytes(&mut self, val: u8, cnt: usize) {
assert!(self.remaining_mut() >= cnt);
if self.len() < cnt {
panic_advance(cnt, self.len());
}
// SAFETY: We just checked that the pointer is valid for `cnt` bytes.
unsafe {
ptr::write_bytes(self.as_mut_ptr(), val, cnt);
self.advance_mut(cnt);
@@ -1432,6 +1533,10 @@ unsafe impl BufMut for &mut [core::mem::MaybeUninit<u8>] {
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
if self.len() < cnt {
panic_advance(cnt, self.len());
}
// Lifetime dance taken from `impl Write for &mut [u8]`.
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b;
@@ -1439,14 +1544,24 @@ unsafe impl BufMut for &mut [core::mem::MaybeUninit<u8>] {
#[inline]
fn put_slice(&mut self, src: &[u8]) {
self.chunk_mut()[..src.len()].copy_from_slice(src);
if self.len() < src.len() {
panic_advance(src.len(), self.len());
}
// SAFETY: We just checked that the pointer is valid for `src.len()` bytes.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr().cast(), src.len());
self.advance_mut(src.len());
}
}
#[inline]
fn put_bytes(&mut self, val: u8, cnt: usize) {
assert!(self.remaining_mut() >= cnt);
if self.len() < cnt {
panic_advance(cnt, self.len());
}
// SAFETY: We just checked that the pointer is valid for `cnt` bytes.
unsafe {
ptr::write_bytes(self.as_mut_ptr() as *mut u8, val, cnt);
self.advance_mut(cnt);
@@ -1466,13 +1581,11 @@ unsafe impl BufMut for Vec<u8> {
let len = self.len();
let remaining = self.capacity() - len;
assert!(
cnt <= remaining,
"cannot advance past `remaining_mut`: {:?} <= {:?}",
cnt,
remaining
);
if remaining < cnt {
panic_advance(cnt, remaining);
}
// Addition will not overflow since the sum is at most the capacity.
self.set_len(len + cnt);
}
@@ -1486,28 +1599,26 @@ unsafe impl BufMut for Vec<u8> {
let len = self.len();
let ptr = self.as_mut_ptr();
unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, cap)[len..] }
// SAFETY: Since `ptr` is valid for `cap` bytes, `ptr.add(len)` must be
// valid for `cap - len` bytes. The subtraction will not underflow since
// `len <= cap`.
unsafe { UninitSlice::from_raw_parts_mut(ptr.add(len), cap - len) }
}
// Specialize these methods so they can skip checking `remaining_mut`
// and `advance_mut`.
#[inline]
fn put<T: super::Buf>(&mut self, mut src: T)
where
Self: Sized,
{
// In case the src isn't contiguous, reserve upfront
// In case the src isn't contiguous, reserve upfront.
self.reserve(src.remaining());
while src.has_remaining() {
let l;
// a block to contain the src.bytes() borrow
{
let s = src.chunk();
l = s.len();
self.extend_from_slice(s);
}
let s = src.chunk();
let l = s.len();
self.extend_from_slice(s);
src.advance(l);
}
}
@@ -1517,8 +1628,10 @@ unsafe impl BufMut for Vec<u8> {
self.extend_from_slice(src);
}
#[inline]
fn put_bytes(&mut self, val: u8, cnt: usize) {
let new_len = self.len().checked_add(cnt).unwrap();
// If the addition overflows, then the `resize` will fail.
let new_len = self.len().saturating_add(cnt);
self.resize(new_len, val);
}
}