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
+117 -51
View File
@@ -1,8 +1,9 @@
#[cfg(feature = "std")]
use crate::buf::{reader, Reader};
use crate::buf::{take, Chain, Take};
use core::{cmp, mem, ptr};
#[cfg(feature = "std")]
use crate::{min_u64_usize, saturating_sub_usize_u64};
use crate::{panic_advance, panic_does_not_fit};
#[cfg(feature = "std")]
use std::io::IoSlice;
@@ -11,7 +12,12 @@ use alloc::boxed::Box;
macro_rules! buf_get_impl {
($this:ident, $typ:tt::$conv:tt) => {{
const SIZE: usize = mem::size_of::<$typ>();
const SIZE: usize = core::mem::size_of::<$typ>();
if $this.remaining() < SIZE {
panic_advance(SIZE, $this.remaining());
}
// try to convert directly from the bytes
// this Option<ret> trick is to avoid keeping a borrow on self
// when advance() is called (mut borrow) and to call bytes() only once
@@ -32,19 +38,30 @@ macro_rules! buf_get_impl {
}
}};
(le => $this:ident, $typ:tt, $len_to_read:expr) => {{
debug_assert!(mem::size_of::<$typ>() >= $len_to_read);
const SIZE: usize = core::mem::size_of::<$typ>();
// The same trick as above does not improve the best case speed.
// It seems to be linked to the way the method is optimised by the compiler
let mut buf = [0; (mem::size_of::<$typ>())];
$this.copy_to_slice(&mut buf[..($len_to_read)]);
let mut buf = [0; SIZE];
let subslice = match buf.get_mut(..$len_to_read) {
Some(subslice) => subslice,
None => panic_does_not_fit(SIZE, $len_to_read),
};
$this.copy_to_slice(subslice);
return $typ::from_le_bytes(buf);
}};
(be => $this:ident, $typ:tt, $len_to_read:expr) => {{
debug_assert!(mem::size_of::<$typ>() >= $len_to_read);
const SIZE: usize = core::mem::size_of::<$typ>();
let mut buf = [0; (mem::size_of::<$typ>())];
$this.copy_to_slice(&mut buf[mem::size_of::<$typ>() - ($len_to_read)..]);
let slice_at = match SIZE.checked_sub($len_to_read) {
Some(slice_at) => slice_at,
None => panic_does_not_fit(SIZE, $len_to_read),
};
let mut buf = [0; SIZE];
$this.copy_to_slice(&mut buf[slice_at..]);
return $typ::from_be_bytes(buf);
}};
}
@@ -247,23 +264,18 @@ pub trait Buf {
///
/// # Panics
///
/// This function panics if `self.remaining() < dst.len()`
fn copy_to_slice(&mut self, dst: &mut [u8]) {
let mut off = 0;
/// This function panics if `self.remaining() < dst.len()`.
fn copy_to_slice(&mut self, mut dst: &mut [u8]) {
if self.remaining() < dst.len() {
panic_advance(dst.len(), self.remaining());
}
assert!(self.remaining() >= dst.len());
while !dst.is_empty() {
let src = self.chunk();
let cnt = usize::min(src.len(), dst.len());
while off < dst.len() {
let cnt;
unsafe {
let src = self.chunk();
cnt = cmp::min(src.len(), dst.len() - off);
ptr::copy_nonoverlapping(src.as_ptr(), dst[off..].as_mut_ptr(), cnt);
off += cnt;
}
dst[..cnt].copy_from_slice(&src[..cnt]);
dst = &mut dst[cnt..];
self.advance(cnt);
}
@@ -286,7 +298,9 @@ pub trait Buf {
///
/// This function panics if there is no more remaining data in `self`.
fn get_u8(&mut self) -> u8 {
assert!(self.remaining() >= 1);
if self.remaining() < 1 {
panic_advance(1, 0);
}
let ret = self.chunk()[0];
self.advance(1);
ret
@@ -309,7 +323,9 @@ pub trait Buf {
///
/// This function panics if there is no more remaining data in `self`.
fn get_i8(&mut self) -> i8 {
assert!(self.remaining() >= 1);
if self.remaining() < 1 {
panic_advance(1, 0);
}
let ret = self.chunk()[0] as i8;
self.advance(1);
ret
@@ -877,7 +893,8 @@ pub trait Buf {
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
/// This function panics if there is not enough remaining data in `self`, or
/// if `nbytes` is greater than 8.
fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
if cfg!(target_endian = "big") {
self.get_uint(nbytes)
@@ -901,7 +918,8 @@ pub trait Buf {
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
/// This function panics if there is not enough remaining data in `self`, or
/// if `nbytes` is greater than 8.
fn get_int(&mut self, nbytes: usize) -> i64 {
buf_get_impl!(be => self, i64, nbytes);
}
@@ -921,7 +939,8 @@ pub trait Buf {
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
/// This function panics if there is not enough remaining data in `self`, or
/// if `nbytes` is greater than 8.
fn get_int_le(&mut self, nbytes: usize) -> i64 {
buf_get_impl!(le => self, i64, nbytes);
}
@@ -944,7 +963,8 @@ pub trait Buf {
///
/// # Panics
///
/// This function panics if there is not enough remaining data in `self`.
/// This function panics if there is not enough remaining data in `self`, or
/// if `nbytes` is greater than 8.
fn get_int_ne(&mut self, nbytes: usize) -> i64 {
if cfg!(target_endian = "big") {
self.get_int(nbytes)
@@ -1103,7 +1123,9 @@ pub trait Buf {
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
use super::BufMut;
assert!(len <= self.remaining(), "`len` greater than remaining");
if self.remaining() < len {
panic_advance(len, self.remaining());
}
let mut ret = crate::BytesMut::with_capacity(len);
ret.put(self.take(len));
@@ -1195,135 +1217,168 @@ pub trait Buf {
macro_rules! deref_forward_buf {
() => {
#[inline]
fn remaining(&self) -> usize {
(**self).remaining()
}
#[inline]
fn chunk(&self) -> &[u8] {
(**self).chunk()
}
#[cfg(feature = "std")]
#[inline]
fn chunks_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
(**self).chunks_vectored(dst)
}
#[inline]
fn advance(&mut self, cnt: usize) {
(**self).advance(cnt)
}
#[inline]
fn has_remaining(&self) -> bool {
(**self).has_remaining()
}
#[inline]
fn copy_to_slice(&mut self, dst: &mut [u8]) {
(**self).copy_to_slice(dst)
}
#[inline]
fn get_u8(&mut self) -> u8 {
(**self).get_u8()
}
#[inline]
fn get_i8(&mut self) -> i8 {
(**self).get_i8()
}
#[inline]
fn get_u16(&mut self) -> u16 {
(**self).get_u16()
}
#[inline]
fn get_u16_le(&mut self) -> u16 {
(**self).get_u16_le()
}
#[inline]
fn get_u16_ne(&mut self) -> u16 {
(**self).get_u16_ne()
}
#[inline]
fn get_i16(&mut self) -> i16 {
(**self).get_i16()
}
#[inline]
fn get_i16_le(&mut self) -> i16 {
(**self).get_i16_le()
}
#[inline]
fn get_i16_ne(&mut self) -> i16 {
(**self).get_i16_ne()
}
#[inline]
fn get_u32(&mut self) -> u32 {
(**self).get_u32()
}
#[inline]
fn get_u32_le(&mut self) -> u32 {
(**self).get_u32_le()
}
#[inline]
fn get_u32_ne(&mut self) -> u32 {
(**self).get_u32_ne()
}
#[inline]
fn get_i32(&mut self) -> i32 {
(**self).get_i32()
}
#[inline]
fn get_i32_le(&mut self) -> i32 {
(**self).get_i32_le()
}
#[inline]
fn get_i32_ne(&mut self) -> i32 {
(**self).get_i32_ne()
}
#[inline]
fn get_u64(&mut self) -> u64 {
(**self).get_u64()
}
#[inline]
fn get_u64_le(&mut self) -> u64 {
(**self).get_u64_le()
}
#[inline]
fn get_u64_ne(&mut self) -> u64 {
(**self).get_u64_ne()
}
#[inline]
fn get_i64(&mut self) -> i64 {
(**self).get_i64()
}
#[inline]
fn get_i64_le(&mut self) -> i64 {
(**self).get_i64_le()
}
#[inline]
fn get_i64_ne(&mut self) -> i64 {
(**self).get_i64_ne()
}
#[inline]
fn get_uint(&mut self, nbytes: usize) -> u64 {
(**self).get_uint(nbytes)
}
#[inline]
fn get_uint_le(&mut self, nbytes: usize) -> u64 {
(**self).get_uint_le(nbytes)
}
#[inline]
fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
(**self).get_uint_ne(nbytes)
}
#[inline]
fn get_int(&mut self, nbytes: usize) -> i64 {
(**self).get_int(nbytes)
}
#[inline]
fn get_int_le(&mut self, nbytes: usize) -> i64 {
(**self).get_int_le(nbytes)
}
#[inline]
fn get_int_ne(&mut self, nbytes: usize) -> i64 {
(**self).get_int_ne(nbytes)
}
#[inline]
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
(**self).copy_to_bytes(len)
}
@@ -1351,41 +1406,52 @@ impl Buf for &[u8] {
#[inline]
fn advance(&mut self, cnt: usize) {
if self.len() < cnt {
panic_advance(cnt, self.len());
}
*self = &self[cnt..];
}
#[inline]
fn copy_to_slice(&mut self, dst: &mut [u8]) {
if self.len() < dst.len() {
panic_advance(dst.len(), self.len());
}
dst.copy_from_slice(&self[..dst.len()]);
self.advance(dst.len());
}
}
#[cfg(feature = "std")]
impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
#[inline]
fn remaining(&self) -> usize {
let len = self.get_ref().as_ref().len();
let pos = self.position();
if pos >= len as u64 {
return 0;
}
len - pos as usize
saturating_sub_usize_u64(self.get_ref().as_ref().len(), self.position())
}
#[inline]
fn chunk(&self) -> &[u8] {
let slice = self.get_ref().as_ref();
let pos = min_u64_usize(self.position(), slice.len());
&slice[pos..]
}
#[inline]
fn advance(&mut self, cnt: usize) {
let len = self.get_ref().as_ref().len();
let pos = self.position();
if pos >= len as u64 {
return &[];
// We intentionally allow `cnt == 0` here even if `pos > len`.
let max_cnt = saturating_sub_usize_u64(len, pos);
if cnt > max_cnt {
panic_advance(cnt, max_cnt);
}
&self.get_ref().as_ref()[pos as usize..]
}
fn advance(&mut self, cnt: usize) {
let pos = (self.position() as usize)
.checked_add(cnt)
.expect("overflow");
assert!(pos <= self.get_ref().as_ref().len());
self.set_position(pos as u64);
// This will not overflow because either `cnt == 0` or the sum is not
// greater than `len`.
self.set_position(pos + cnt as u64);
}
}
+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);
}
}
+1 -1
View File
@@ -135,7 +135,7 @@ where
U: Buf,
{
fn remaining(&self) -> usize {
self.a.remaining().checked_add(self.b.remaining()).unwrap()
self.a.remaining().saturating_add(self.b.remaining())
}
fn chunk(&self) -> &[u8] {
+1 -1
View File
@@ -184,7 +184,7 @@ impl UninitSlice {
/// };
/// ```
#[inline]
pub unsafe fn as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>] {
pub unsafe fn as_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
&mut *(self as *mut _ as *mut [MaybeUninit<u8>])
}
+1 -1
View File
@@ -242,7 +242,7 @@ impl Bytes {
let begin = match range.start_bound() {
Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1,
Bound::Excluded(&n) => n.checked_add(1).expect("out of range"),
Bound::Unbounded => 0,
};
+6 -8
View File
@@ -1087,14 +1087,12 @@ unsafe impl BufMut for BytesMut {
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
let new_len = self.len() + cnt;
assert!(
new_len <= self.cap,
"new_len = {}; capacity = {}",
new_len,
self.cap
);
self.len = new_len;
let remaining = self.cap - self.len();
if cnt > remaining {
super::panic_advance(cnt, remaining);
}
// Addition won't overflow since it is at most `self.cap`.
self.len = self.len() + cnt;
}
#[inline]
+37
View File
@@ -115,3 +115,40 @@ fn abort() -> ! {
panic!("abort");
}
}
#[inline(always)]
#[cfg(feature = "std")]
fn saturating_sub_usize_u64(a: usize, b: u64) -> usize {
use core::convert::TryFrom;
match usize::try_from(b) {
Ok(b) => a.saturating_sub(b),
Err(_) => 0,
}
}
#[inline(always)]
#[cfg(feature = "std")]
fn min_u64_usize(a: u64, b: usize) -> usize {
use core::convert::TryFrom;
match usize::try_from(a) {
Ok(a) => usize::min(a, b),
Err(_) => b,
}
}
/// Panic with a nice error message.
#[cold]
fn panic_advance(idx: usize, len: usize) -> ! {
panic!(
"advance out of bounds: the len is {} but advancing by {}",
len, idx
);
}
#[cold]
fn panic_does_not_fit(size: usize, nbytes: usize) -> ! {
panic!(
"size too large: the integer type can fit {} bytes, but nbytes is {}",
size, nbytes
);
}
+1 -1
View File
@@ -83,7 +83,7 @@ fn test_put_int_le_nbytes_overflow() {
}
#[test]
#[should_panic(expected = "cannot advance")]
#[should_panic(expected = "advance out of bounds: the len is 8 but advancing by 12")]
fn test_vec_advance_mut() {
// Verify fix for #354
let mut buf = Vec::with_capacity(8);