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")] #[cfg(feature = "std")]
use crate::buf::{reader, Reader}; use crate::buf::{reader, Reader};
use crate::buf::{take, Chain, Take}; use crate::buf::{take, Chain, Take};
#[cfg(feature = "std")]
use core::{cmp, mem, ptr}; use crate::{min_u64_usize, saturating_sub_usize_u64};
use crate::{panic_advance, panic_does_not_fit};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::io::IoSlice; use std::io::IoSlice;
@@ -11,7 +12,12 @@ use alloc::boxed::Box;
macro_rules! buf_get_impl { macro_rules! buf_get_impl {
($this:ident, $typ:tt::$conv:tt) => {{ ($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 // try to convert directly from the bytes
// this Option<ret> trick is to avoid keeping a borrow on self // this Option<ret> trick is to avoid keeping a borrow on self
// when advance() is called (mut borrow) and to call bytes() only once // 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) => {{ (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. // 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 // It seems to be linked to the way the method is optimised by the compiler
let mut buf = [0; (mem::size_of::<$typ>())]; let mut buf = [0; SIZE];
$this.copy_to_slice(&mut buf[..($len_to_read)]);
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); return $typ::from_le_bytes(buf);
}}; }};
(be => $this:ident, $typ:tt, $len_to_read:expr) => {{ (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>())]; let slice_at = match SIZE.checked_sub($len_to_read) {
$this.copy_to_slice(&mut buf[mem::size_of::<$typ>() - ($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); return $typ::from_be_bytes(buf);
}}; }};
} }
@@ -247,23 +264,18 @@ pub trait Buf {
/// ///
/// # Panics /// # Panics
/// ///
/// This function panics if `self.remaining() < dst.len()` /// This function panics if `self.remaining() < dst.len()`.
fn copy_to_slice(&mut self, dst: &mut [u8]) { fn copy_to_slice(&mut self, mut dst: &mut [u8]) {
let mut off = 0; 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() { dst[..cnt].copy_from_slice(&src[..cnt]);
let cnt; dst = &mut dst[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;
}
self.advance(cnt); self.advance(cnt);
} }
@@ -286,7 +298,9 @@ pub trait Buf {
/// ///
/// This function panics if there is no more remaining data in `self`. /// This function panics if there is no more remaining data in `self`.
fn get_u8(&mut self) -> u8 { fn get_u8(&mut self) -> u8 {
assert!(self.remaining() >= 1); if self.remaining() < 1 {
panic_advance(1, 0);
}
let ret = self.chunk()[0]; let ret = self.chunk()[0];
self.advance(1); self.advance(1);
ret ret
@@ -309,7 +323,9 @@ pub trait Buf {
/// ///
/// This function panics if there is no more remaining data in `self`. /// This function panics if there is no more remaining data in `self`.
fn get_i8(&mut self) -> i8 { 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; let ret = self.chunk()[0] as i8;
self.advance(1); self.advance(1);
ret ret
@@ -877,7 +893,8 @@ pub trait Buf {
/// ///
/// # Panics /// # 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 { fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
if cfg!(target_endian = "big") { if cfg!(target_endian = "big") {
self.get_uint(nbytes) self.get_uint(nbytes)
@@ -901,7 +918,8 @@ pub trait Buf {
/// ///
/// # Panics /// # 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 { fn get_int(&mut self, nbytes: usize) -> i64 {
buf_get_impl!(be => self, i64, nbytes); buf_get_impl!(be => self, i64, nbytes);
} }
@@ -921,7 +939,8 @@ pub trait Buf {
/// ///
/// # Panics /// # 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 { fn get_int_le(&mut self, nbytes: usize) -> i64 {
buf_get_impl!(le => self, i64, nbytes); buf_get_impl!(le => self, i64, nbytes);
} }
@@ -944,7 +963,8 @@ pub trait Buf {
/// ///
/// # Panics /// # 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 { fn get_int_ne(&mut self, nbytes: usize) -> i64 {
if cfg!(target_endian = "big") { if cfg!(target_endian = "big") {
self.get_int(nbytes) self.get_int(nbytes)
@@ -1103,7 +1123,9 @@ pub trait Buf {
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
use super::BufMut; 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); let mut ret = crate::BytesMut::with_capacity(len);
ret.put(self.take(len)); ret.put(self.take(len));
@@ -1195,135 +1217,168 @@ pub trait Buf {
macro_rules! deref_forward_buf { macro_rules! deref_forward_buf {
() => { () => {
#[inline]
fn remaining(&self) -> usize { fn remaining(&self) -> usize {
(**self).remaining() (**self).remaining()
} }
#[inline]
fn chunk(&self) -> &[u8] { fn chunk(&self) -> &[u8] {
(**self).chunk() (**self).chunk()
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[inline]
fn chunks_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize { fn chunks_vectored<'b>(&'b self, dst: &mut [IoSlice<'b>]) -> usize {
(**self).chunks_vectored(dst) (**self).chunks_vectored(dst)
} }
#[inline]
fn advance(&mut self, cnt: usize) { fn advance(&mut self, cnt: usize) {
(**self).advance(cnt) (**self).advance(cnt)
} }
#[inline]
fn has_remaining(&self) -> bool { fn has_remaining(&self) -> bool {
(**self).has_remaining() (**self).has_remaining()
} }
#[inline]
fn copy_to_slice(&mut self, dst: &mut [u8]) { fn copy_to_slice(&mut self, dst: &mut [u8]) {
(**self).copy_to_slice(dst) (**self).copy_to_slice(dst)
} }
#[inline]
fn get_u8(&mut self) -> u8 { fn get_u8(&mut self) -> u8 {
(**self).get_u8() (**self).get_u8()
} }
#[inline]
fn get_i8(&mut self) -> i8 { fn get_i8(&mut self) -> i8 {
(**self).get_i8() (**self).get_i8()
} }
#[inline]
fn get_u16(&mut self) -> u16 { fn get_u16(&mut self) -> u16 {
(**self).get_u16() (**self).get_u16()
} }
#[inline]
fn get_u16_le(&mut self) -> u16 { fn get_u16_le(&mut self) -> u16 {
(**self).get_u16_le() (**self).get_u16_le()
} }
#[inline]
fn get_u16_ne(&mut self) -> u16 { fn get_u16_ne(&mut self) -> u16 {
(**self).get_u16_ne() (**self).get_u16_ne()
} }
#[inline]
fn get_i16(&mut self) -> i16 { fn get_i16(&mut self) -> i16 {
(**self).get_i16() (**self).get_i16()
} }
#[inline]
fn get_i16_le(&mut self) -> i16 { fn get_i16_le(&mut self) -> i16 {
(**self).get_i16_le() (**self).get_i16_le()
} }
#[inline]
fn get_i16_ne(&mut self) -> i16 { fn get_i16_ne(&mut self) -> i16 {
(**self).get_i16_ne() (**self).get_i16_ne()
} }
#[inline]
fn get_u32(&mut self) -> u32 { fn get_u32(&mut self) -> u32 {
(**self).get_u32() (**self).get_u32()
} }
#[inline]
fn get_u32_le(&mut self) -> u32 { fn get_u32_le(&mut self) -> u32 {
(**self).get_u32_le() (**self).get_u32_le()
} }
#[inline]
fn get_u32_ne(&mut self) -> u32 { fn get_u32_ne(&mut self) -> u32 {
(**self).get_u32_ne() (**self).get_u32_ne()
} }
#[inline]
fn get_i32(&mut self) -> i32 { fn get_i32(&mut self) -> i32 {
(**self).get_i32() (**self).get_i32()
} }
#[inline]
fn get_i32_le(&mut self) -> i32 { fn get_i32_le(&mut self) -> i32 {
(**self).get_i32_le() (**self).get_i32_le()
} }
#[inline]
fn get_i32_ne(&mut self) -> i32 { fn get_i32_ne(&mut self) -> i32 {
(**self).get_i32_ne() (**self).get_i32_ne()
} }
#[inline]
fn get_u64(&mut self) -> u64 { fn get_u64(&mut self) -> u64 {
(**self).get_u64() (**self).get_u64()
} }
#[inline]
fn get_u64_le(&mut self) -> u64 { fn get_u64_le(&mut self) -> u64 {
(**self).get_u64_le() (**self).get_u64_le()
} }
#[inline]
fn get_u64_ne(&mut self) -> u64 { fn get_u64_ne(&mut self) -> u64 {
(**self).get_u64_ne() (**self).get_u64_ne()
} }
#[inline]
fn get_i64(&mut self) -> i64 { fn get_i64(&mut self) -> i64 {
(**self).get_i64() (**self).get_i64()
} }
#[inline]
fn get_i64_le(&mut self) -> i64 { fn get_i64_le(&mut self) -> i64 {
(**self).get_i64_le() (**self).get_i64_le()
} }
#[inline]
fn get_i64_ne(&mut self) -> i64 { fn get_i64_ne(&mut self) -> i64 {
(**self).get_i64_ne() (**self).get_i64_ne()
} }
#[inline]
fn get_uint(&mut self, nbytes: usize) -> u64 { fn get_uint(&mut self, nbytes: usize) -> u64 {
(**self).get_uint(nbytes) (**self).get_uint(nbytes)
} }
#[inline]
fn get_uint_le(&mut self, nbytes: usize) -> u64 { fn get_uint_le(&mut self, nbytes: usize) -> u64 {
(**self).get_uint_le(nbytes) (**self).get_uint_le(nbytes)
} }
#[inline]
fn get_uint_ne(&mut self, nbytes: usize) -> u64 { fn get_uint_ne(&mut self, nbytes: usize) -> u64 {
(**self).get_uint_ne(nbytes) (**self).get_uint_ne(nbytes)
} }
#[inline]
fn get_int(&mut self, nbytes: usize) -> i64 { fn get_int(&mut self, nbytes: usize) -> i64 {
(**self).get_int(nbytes) (**self).get_int(nbytes)
} }
#[inline]
fn get_int_le(&mut self, nbytes: usize) -> i64 { fn get_int_le(&mut self, nbytes: usize) -> i64 {
(**self).get_int_le(nbytes) (**self).get_int_le(nbytes)
} }
#[inline]
fn get_int_ne(&mut self, nbytes: usize) -> i64 { fn get_int_ne(&mut self, nbytes: usize) -> i64 {
(**self).get_int_ne(nbytes) (**self).get_int_ne(nbytes)
} }
#[inline]
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes { fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
(**self).copy_to_bytes(len) (**self).copy_to_bytes(len)
} }
@@ -1351,41 +1406,52 @@ impl Buf for &[u8] {
#[inline] #[inline]
fn advance(&mut self, cnt: usize) { fn advance(&mut self, cnt: usize) {
if self.len() < cnt {
panic_advance(cnt, self.len());
}
*self = &self[cnt..]; *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")] #[cfg(feature = "std")]
impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> { impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
#[inline]
fn remaining(&self) -> usize { fn remaining(&self) -> usize {
let len = self.get_ref().as_ref().len(); saturating_sub_usize_u64(self.get_ref().as_ref().len(), self.position())
let pos = self.position();
if pos >= len as u64 {
return 0;
}
len - pos as usize
} }
#[inline]
fn chunk(&self) -> &[u8] { 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 len = self.get_ref().as_ref().len();
let pos = self.position(); let pos = self.position();
if pos >= len as u64 { // We intentionally allow `cnt == 0` here even if `pos > len`.
return &[]; 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..] // This will not overflow because either `cnt == 0` or the sum is not
} // greater than `len`.
self.set_position(pos + cnt as u64);
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);
} }
} }
+187 -74
View File
@@ -1,8 +1,9 @@
use crate::buf::{limit, Chain, Limit, UninitSlice}; use crate::buf::{limit, Chain, Limit, UninitSlice};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::buf::{writer, Writer}; 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}; 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 /// The next call to `chunk_mut` will return a slice starting `cnt` bytes
/// further into the underlying buffer. /// further into the underlying buffer.
/// ///
/// This function is unsafe because there is no guarantee that the bytes /// # Safety
/// being advanced past have been initialized. ///
/// The caller must ensure that the next `cnt` bytes of `chunk` are
/// initialized.
/// ///
/// # Examples /// # Examples
/// ///
@@ -121,6 +124,7 @@ pub unsafe trait BufMut {
/// ///
/// assert!(!buf.has_remaining_mut()); /// assert!(!buf.has_remaining_mut());
/// ``` /// ```
#[inline]
fn has_remaining_mut(&self) -> bool { fn has_remaining_mut(&self) -> bool {
self.remaining_mut() > 0 self.remaining_mut() > 0
} }
@@ -194,27 +198,25 @@ pub unsafe trait BufMut {
/// # Panics /// # Panics
/// ///
/// Panics if `self` does not have enough capacity to contain `src`. /// Panics if `self` does not have enough capacity to contain `src`.
#[inline]
fn put<T: super::Buf>(&mut self, mut src: T) fn put<T: super::Buf>(&mut self, mut src: T)
where where
Self: Sized, 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() { while src.has_remaining() {
let l; let s = src.chunk();
let d = self.chunk_mut();
let cnt = usize::min(s.len(), d.len());
unsafe { d[..cnt].copy_from_slice(&s[..cnt]);
let s = src.chunk();
let d = self.chunk_mut();
l = cmp::min(s.len(), d.len());
ptr::copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr() as *mut u8, l); // SAFETY: We just initialized `cnt` bytes in `self`.
} unsafe { self.advance_mut(cnt) };
src.advance(cnt);
src.advance(l);
unsafe {
self.advance_mut(l);
}
} }
} }
@@ -237,31 +239,21 @@ pub unsafe trait BufMut {
/// ///
/// assert_eq!(b"hello\0", &dst); /// assert_eq!(b"hello\0", &dst);
/// ``` /// ```
fn put_slice(&mut self, src: &[u8]) { #[inline]
let mut off = 0; fn put_slice(&mut self, mut src: &[u8]) {
if self.remaining_mut() < src.len() {
panic_advance(src.len(), self.remaining_mut());
}
assert!( while !src.is_empty() {
self.remaining_mut() >= src.len(), let dst = self.chunk_mut();
"buffer overflow; remaining = {}; src = {}", let cnt = usize::min(src.len(), dst.len());
self.remaining_mut(),
src.len()
);
while off < src.len() { dst[..cnt].copy_from_slice(&src[..cnt]);
let cnt; src = &src[cnt..];
unsafe { // SAFETY: We just initialized `cnt` bytes in `self`.
let dst = self.chunk_mut(); unsafe { self.advance_mut(cnt) };
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);
}
} }
} }
@@ -290,9 +282,20 @@ pub unsafe trait BufMut {
/// ///
/// This function panics if there is not enough remaining capacity in /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
fn put_bytes(&mut self, val: u8, cnt: usize) { #[inline]
for _ in 0..cnt { fn put_bytes(&mut self, val: u8, mut cnt: usize) {
self.put_u8(val); 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u8(&mut self, n: u8) { fn put_u8(&mut self, n: u8) {
let src = [n]; let src = [n];
self.put_slice(&src); self.put_slice(&src);
@@ -337,6 +341,7 @@ pub unsafe trait BufMut {
/// ///
/// This function panics if there is not enough remaining capacity in /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i8(&mut self, n: i8) { fn put_i8(&mut self, n: i8) {
let src = [n as u8]; let src = [n as u8];
self.put_slice(&src) self.put_slice(&src)
@@ -360,6 +365,7 @@ pub unsafe trait BufMut {
/// ///
/// This function panics if there is not enough remaining capacity in /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u16(&mut self, n: u16) { fn put_u16(&mut self, n: u16) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u16_le(&mut self, n: u16) { fn put_u16_le(&mut self, n: u16) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u16_ne(&mut self, n: u16) { fn put_u16_ne(&mut self, n: u16) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i16(&mut self, n: i16) { fn put_i16(&mut self, n: i16) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i16_le(&mut self, n: i16) { fn put_i16_le(&mut self, n: i16) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i16_ne(&mut self, n: i16) { fn put_i16_ne(&mut self, n: i16) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u32(&mut self, n: u32) { fn put_u32(&mut self, n: u32) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u32_le(&mut self, n: u32) { fn put_u32_le(&mut self, n: u32) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u32_ne(&mut self, n: u32) { fn put_u32_ne(&mut self, n: u32) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i32(&mut self, n: i32) { fn put_i32(&mut self, n: i32) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i32_le(&mut self, n: i32) { fn put_i32_le(&mut self, n: i32) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i32_ne(&mut self, n: i32) { fn put_i32_ne(&mut self, n: i32) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u64(&mut self, n: u64) { fn put_u64(&mut self, n: u64) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u64_le(&mut self, n: u64) { fn put_u64_le(&mut self, n: u64) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u64_ne(&mut self, n: u64) { fn put_u64_ne(&mut self, n: u64) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i64(&mut self, n: i64) { fn put_i64(&mut self, n: i64) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i64_le(&mut self, n: i64) { fn put_i64_le(&mut self, n: i64) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i64_ne(&mut self, n: i64) { fn put_i64_ne(&mut self, n: i64) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u128(&mut self, n: u128) { fn put_u128(&mut self, n: u128) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u128_le(&mut self, n: u128) { fn put_u128_le(&mut self, n: u128) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_u128_ne(&mut self, n: u128) { fn put_u128_ne(&mut self, n: u128) {
self.put_slice(&n.to_ne_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i128(&mut self, n: i128) { fn put_i128(&mut self, n: i128) {
self.put_slice(&n.to_be_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i128_le(&mut self, n: i128) { fn put_i128_le(&mut self, n: i128) {
self.put_slice(&n.to_le_bytes()) 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_i128_ne(&mut self, n: i128) { fn put_i128_ne(&mut self, n: i128) {
self.put_slice(&n.to_ne_bytes()) self.put_slice(&n.to_ne_bytes())
} }
@@ -919,9 +948,15 @@ pub unsafe trait BufMut {
/// # Panics /// # Panics
/// ///
/// This function panics if there is not enough remaining capacity in /// 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) { 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. /// Writes an unsigned n-byte integer to `self` in the little-endian byte order.
@@ -941,9 +976,16 @@ pub unsafe trait BufMut {
/// # Panics /// # Panics
/// ///
/// This function panics if there is not enough remaining capacity in /// 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) { 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. /// Writes an unsigned n-byte integer to `self` in the native-endian byte order.
@@ -967,7 +1009,8 @@ pub unsafe trait BufMut {
/// # Panics /// # Panics
/// ///
/// This function panics if there is not enough remaining capacity in /// 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) { fn put_uint_ne(&mut self, n: u64, nbytes: usize) {
if cfg!(target_endian = "big") { if cfg!(target_endian = "big") {
self.put_uint(n, nbytes) self.put_uint(n, nbytes)
@@ -994,8 +1037,14 @@ pub unsafe trait BufMut {
/// ///
/// This function panics if there is not enough remaining capacity in /// This function panics if there is not enough remaining capacity in
/// `self` or if `nbytes` is greater than 8. /// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_int(&mut self, n: i64, nbytes: usize) { 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. /// 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 /// This function panics if there is not enough remaining capacity in
/// `self` or if `nbytes` is greater than 8. /// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_int_le(&mut self, n: i64, nbytes: usize) { 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. /// 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 /// This function panics if there is not enough remaining capacity in
/// `self` or if `nbytes` is greater than 8. /// `self` or if `nbytes` is greater than 8.
#[inline]
fn put_int_ne(&mut self, n: i64, nbytes: usize) { fn put_int_ne(&mut self, n: i64, nbytes: usize) {
if cfg!(target_endian = "big") { if cfg!(target_endian = "big") {
self.put_int(n, nbytes) self.put_int(n, nbytes)
@@ -1069,6 +1126,7 @@ pub unsafe trait BufMut {
/// ///
/// This function panics if there is not enough remaining capacity in /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_f32(&mut self, n: f32) { fn put_f32(&mut self, n: f32) {
self.put_u32(n.to_bits()); 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_f32_le(&mut self, n: f32) { fn put_f32_le(&mut self, n: f32) {
self.put_u32_le(n.to_bits()); 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_f32_ne(&mut self, n: f32) { fn put_f32_ne(&mut self, n: f32) {
self.put_u32_ne(n.to_bits()); 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_f64(&mut self, n: f64) { fn put_f64(&mut self, n: f64) {
self.put_u64(n.to_bits()); 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_f64_le(&mut self, n: f64) { fn put_f64_le(&mut self, n: f64) {
self.put_u64_le(n.to_bits()); 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 /// This function panics if there is not enough remaining capacity in
/// `self`. /// `self`.
#[inline]
fn put_f64_ne(&mut self, n: f64) { fn put_f64_ne(&mut self, n: f64) {
self.put_u64_ne(n.to_bits()); self.put_u64_ne(n.to_bits());
} }
@@ -1209,6 +1272,7 @@ pub unsafe trait BufMut {
/// let dst = arr.limit(10); /// let dst = arr.limit(10);
/// assert_eq!(dst.remaining_mut(), 10); /// assert_eq!(dst.remaining_mut(), 10);
/// ``` /// ```
#[inline]
fn limit(self, limit: usize) -> Limit<Self> fn limit(self, limit: usize) -> Limit<Self>
where where
Self: Sized, Self: Sized,
@@ -1240,6 +1304,7 @@ pub unsafe trait BufMut {
/// ``` /// ```
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[inline]
fn writer(self) -> Writer<Self> fn writer(self) -> Writer<Self>
where where
Self: Sized, Self: Sized,
@@ -1267,6 +1332,7 @@ pub unsafe trait BufMut {
/// assert_eq!(&a[..], b"hello"); /// assert_eq!(&a[..], b"hello");
/// assert_eq!(&b[..], b" world"); /// assert_eq!(&b[..], b" world");
/// ``` /// ```
#[inline]
fn chain_mut<U: BufMut>(self, next: U) -> Chain<Self, U> fn chain_mut<U: BufMut>(self, next: U) -> Chain<Self, U>
where where
Self: Sized, Self: Sized,
@@ -1277,98 +1343,122 @@ pub unsafe trait BufMut {
macro_rules! deref_forward_bufmut { macro_rules! deref_forward_bufmut {
() => { () => {
#[inline]
fn remaining_mut(&self) -> usize { fn remaining_mut(&self) -> usize {
(**self).remaining_mut() (**self).remaining_mut()
} }
#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice { fn chunk_mut(&mut self) -> &mut UninitSlice {
(**self).chunk_mut() (**self).chunk_mut()
} }
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) { unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt) (**self).advance_mut(cnt)
} }
#[inline]
fn put_slice(&mut self, src: &[u8]) { fn put_slice(&mut self, src: &[u8]) {
(**self).put_slice(src) (**self).put_slice(src)
} }
#[inline]
fn put_u8(&mut self, n: u8) { fn put_u8(&mut self, n: u8) {
(**self).put_u8(n) (**self).put_u8(n)
} }
#[inline]
fn put_i8(&mut self, n: i8) { fn put_i8(&mut self, n: i8) {
(**self).put_i8(n) (**self).put_i8(n)
} }
#[inline]
fn put_u16(&mut self, n: u16) { fn put_u16(&mut self, n: u16) {
(**self).put_u16(n) (**self).put_u16(n)
} }
#[inline]
fn put_u16_le(&mut self, n: u16) { fn put_u16_le(&mut self, n: u16) {
(**self).put_u16_le(n) (**self).put_u16_le(n)
} }
#[inline]
fn put_u16_ne(&mut self, n: u16) { fn put_u16_ne(&mut self, n: u16) {
(**self).put_u16_ne(n) (**self).put_u16_ne(n)
} }
#[inline]
fn put_i16(&mut self, n: i16) { fn put_i16(&mut self, n: i16) {
(**self).put_i16(n) (**self).put_i16(n)
} }
#[inline]
fn put_i16_le(&mut self, n: i16) { fn put_i16_le(&mut self, n: i16) {
(**self).put_i16_le(n) (**self).put_i16_le(n)
} }
#[inline]
fn put_i16_ne(&mut self, n: i16) { fn put_i16_ne(&mut self, n: i16) {
(**self).put_i16_ne(n) (**self).put_i16_ne(n)
} }
#[inline]
fn put_u32(&mut self, n: u32) { fn put_u32(&mut self, n: u32) {
(**self).put_u32(n) (**self).put_u32(n)
} }
#[inline]
fn put_u32_le(&mut self, n: u32) { fn put_u32_le(&mut self, n: u32) {
(**self).put_u32_le(n) (**self).put_u32_le(n)
} }
#[inline]
fn put_u32_ne(&mut self, n: u32) { fn put_u32_ne(&mut self, n: u32) {
(**self).put_u32_ne(n) (**self).put_u32_ne(n)
} }
#[inline]
fn put_i32(&mut self, n: i32) { fn put_i32(&mut self, n: i32) {
(**self).put_i32(n) (**self).put_i32(n)
} }
#[inline]
fn put_i32_le(&mut self, n: i32) { fn put_i32_le(&mut self, n: i32) {
(**self).put_i32_le(n) (**self).put_i32_le(n)
} }
#[inline]
fn put_i32_ne(&mut self, n: i32) { fn put_i32_ne(&mut self, n: i32) {
(**self).put_i32_ne(n) (**self).put_i32_ne(n)
} }
#[inline]
fn put_u64(&mut self, n: u64) { fn put_u64(&mut self, n: u64) {
(**self).put_u64(n) (**self).put_u64(n)
} }
#[inline]
fn put_u64_le(&mut self, n: u64) { fn put_u64_le(&mut self, n: u64) {
(**self).put_u64_le(n) (**self).put_u64_le(n)
} }
#[inline]
fn put_u64_ne(&mut self, n: u64) { fn put_u64_ne(&mut self, n: u64) {
(**self).put_u64_ne(n) (**self).put_u64_ne(n)
} }
#[inline]
fn put_i64(&mut self, n: i64) { fn put_i64(&mut self, n: i64) {
(**self).put_i64(n) (**self).put_i64(n)
} }
#[inline]
fn put_i64_le(&mut self, n: i64) { fn put_i64_le(&mut self, n: i64) {
(**self).put_i64_le(n) (**self).put_i64_le(n)
} }
#[inline]
fn put_i64_ne(&mut self, n: i64) { fn put_i64_ne(&mut self, n: i64) {
(**self).put_i64_ne(n) (**self).put_i64_ne(n)
} }
@@ -1391,12 +1481,15 @@ unsafe impl BufMut for &mut [u8] {
#[inline] #[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice { fn chunk_mut(&mut self) -> &mut UninitSlice {
// UninitSlice is repr(transparent), so safe to transmute UninitSlice::new(self)
unsafe { &mut *(*self as *mut [u8] as *mut _) }
} }
#[inline] #[inline]
unsafe fn advance_mut(&mut self, cnt: usize) { 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]`. // Lifetime dance taken from `impl Write for &mut [u8]`.
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt); let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b; *self = b;
@@ -1404,14 +1497,22 @@ unsafe impl BufMut for &mut [u8] {
#[inline] #[inline]
fn put_slice(&mut self, src: &[u8]) { fn put_slice(&mut self, src: &[u8]) {
self[..src.len()].copy_from_slice(src); if self.len() < src.len() {
unsafe { panic_advance(src.len(), self.len());
self.advance_mut(src.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) { 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 { unsafe {
ptr::write_bytes(self.as_mut_ptr(), val, cnt); ptr::write_bytes(self.as_mut_ptr(), val, cnt);
self.advance_mut(cnt); self.advance_mut(cnt);
@@ -1432,6 +1533,10 @@ unsafe impl BufMut for &mut [core::mem::MaybeUninit<u8>] {
#[inline] #[inline]
unsafe fn advance_mut(&mut self, cnt: usize) { 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]`. // Lifetime dance taken from `impl Write for &mut [u8]`.
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt); let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b; *self = b;
@@ -1439,14 +1544,24 @@ unsafe impl BufMut for &mut [core::mem::MaybeUninit<u8>] {
#[inline] #[inline]
fn put_slice(&mut self, src: &[u8]) { 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 { unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr().cast(), src.len());
self.advance_mut(src.len()); self.advance_mut(src.len());
} }
} }
#[inline]
fn put_bytes(&mut self, val: u8, cnt: usize) { 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 { unsafe {
ptr::write_bytes(self.as_mut_ptr() as *mut u8, val, cnt); ptr::write_bytes(self.as_mut_ptr() as *mut u8, val, cnt);
self.advance_mut(cnt); self.advance_mut(cnt);
@@ -1466,13 +1581,11 @@ unsafe impl BufMut for Vec<u8> {
let len = self.len(); let len = self.len();
let remaining = self.capacity() - len; let remaining = self.capacity() - len;
assert!( if remaining < cnt {
cnt <= remaining, panic_advance(cnt, remaining);
"cannot advance past `remaining_mut`: {:?} <= {:?}", }
cnt,
remaining
);
// Addition will not overflow since the sum is at most the capacity.
self.set_len(len + cnt); self.set_len(len + cnt);
} }
@@ -1486,28 +1599,26 @@ unsafe impl BufMut for Vec<u8> {
let len = self.len(); let len = self.len();
let ptr = self.as_mut_ptr(); 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` // Specialize these methods so they can skip checking `remaining_mut`
// and `advance_mut`. // and `advance_mut`.
#[inline]
fn put<T: super::Buf>(&mut self, mut src: T) fn put<T: super::Buf>(&mut self, mut src: T)
where where
Self: Sized, Self: Sized,
{ {
// In case the src isn't contiguous, reserve upfront // In case the src isn't contiguous, reserve upfront.
self.reserve(src.remaining()); self.reserve(src.remaining());
while src.has_remaining() { while src.has_remaining() {
let l; let s = src.chunk();
let l = s.len();
// a block to contain the src.bytes() borrow self.extend_from_slice(s);
{
let s = src.chunk();
l = s.len();
self.extend_from_slice(s);
}
src.advance(l); src.advance(l);
} }
} }
@@ -1517,8 +1628,10 @@ unsafe impl BufMut for Vec<u8> {
self.extend_from_slice(src); self.extend_from_slice(src);
} }
#[inline]
fn put_bytes(&mut self, val: u8, cnt: usize) { 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); self.resize(new_len, val);
} }
} }
+1 -1
View File
@@ -135,7 +135,7 @@ where
U: Buf, U: Buf,
{ {
fn remaining(&self) -> usize { 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] { fn chunk(&self) -> &[u8] {
+1 -1
View File
@@ -184,7 +184,7 @@ impl UninitSlice {
/// }; /// };
/// ``` /// ```
#[inline] #[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>]) &mut *(self as *mut _ as *mut [MaybeUninit<u8>])
} }
+1 -1
View File
@@ -242,7 +242,7 @@ impl Bytes {
let begin = match range.start_bound() { let begin = match range.start_bound() {
Bound::Included(&n) => n, Bound::Included(&n) => n,
Bound::Excluded(&n) => n + 1, Bound::Excluded(&n) => n.checked_add(1).expect("out of range"),
Bound::Unbounded => 0, Bound::Unbounded => 0,
}; };
+6 -8
View File
@@ -1087,14 +1087,12 @@ unsafe impl BufMut for BytesMut {
#[inline] #[inline]
unsafe fn advance_mut(&mut self, cnt: usize) { unsafe fn advance_mut(&mut self, cnt: usize) {
let new_len = self.len() + cnt; let remaining = self.cap - self.len();
assert!( if cnt > remaining {
new_len <= self.cap, super::panic_advance(cnt, remaining);
"new_len = {}; capacity = {}", }
new_len, // Addition won't overflow since it is at most `self.cap`.
self.cap self.len = self.len() + cnt;
);
self.len = new_len;
} }
#[inline] #[inline]
+37
View File
@@ -115,3 +115,40 @@ fn abort() -> ! {
panic!("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] #[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() { fn test_vec_advance_mut() {
// Verify fix for #354 // Verify fix for #354
let mut buf = Vec::with_capacity(8); let mut buf = Vec::with_capacity(8);