use core::{
cmp,
mem::{self, MaybeUninit},
ptr, usize,
};
#[cfg(feature = "std")]
use std::fmt;
use alloc::{boxed::Box, vec::Vec};
pub trait BufMut {
fn remaining_mut(&self) -> usize;
unsafe fn advance_mut(&mut self, cnt: usize);
fn has_remaining_mut(&self) -> bool {
self.remaining_mut() > 0
}
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>];
#[cfg(feature = "std")]
fn bytes_vectored_mut<'a>(&'a mut self, dst: &mut [IoSliceMut<'a>]) -> usize {
if dst.is_empty() {
return 0;
}
if self.has_remaining_mut() {
dst[0] = IoSliceMut::from(self.bytes_mut());
1
} else {
0
}
}
fn put<T: super::Buf>(&mut self, mut src: T)
where
Self: Sized,
{
assert!(self.remaining_mut() >= src.remaining());
while src.has_remaining() {
let l;
unsafe {
let s = src.bytes();
let d = self.bytes_mut();
l = cmp::min(s.len(), d.len());
ptr::copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr() as *mut u8, l);
}
src.advance(l);
unsafe {
self.advance_mut(l);
}
}
}
fn put_slice(&mut self, src: &[u8]) {
let mut off = 0;
assert!(
self.remaining_mut() >= src.len(),
"buffer overflow; remaining = {}; src = {}",
self.remaining_mut(),
src.len()
);
while off < src.len() {
let cnt;
unsafe {
let dst = self.bytes_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);
}
}
}
fn put_u8(&mut self, n: u8) {
let src = [n];
self.put_slice(&src);
}
fn put_i8(&mut self, n: i8) {
let src = [n as u8];
self.put_slice(&src)
}
fn put_u16(&mut self, n: u16) {
self.put_slice(&n.to_be_bytes())
}
fn put_u16_le(&mut self, n: u16) {
self.put_slice(&n.to_le_bytes())
}
fn put_i16(&mut self, n: i16) {
self.put_slice(&n.to_be_bytes())
}
fn put_i16_le(&mut self, n: i16) {
self.put_slice(&n.to_le_bytes())
}
fn put_u32(&mut self, n: u32) {
self.put_slice(&n.to_be_bytes())
}
fn put_u32_le(&mut self, n: u32) {
self.put_slice(&n.to_le_bytes())
}
fn put_i32(&mut self, n: i32) {
self.put_slice(&n.to_be_bytes())
}
fn put_i32_le(&mut self, n: i32) {
self.put_slice(&n.to_le_bytes())
}
fn put_u64(&mut self, n: u64) {
self.put_slice(&n.to_be_bytes())
}
fn put_u64_le(&mut self, n: u64) {
self.put_slice(&n.to_le_bytes())
}
fn put_i64(&mut self, n: i64) {
self.put_slice(&n.to_be_bytes())
}
fn put_i64_le(&mut self, n: i64) {
self.put_slice(&n.to_le_bytes())
}
fn put_u128(&mut self, n: u128) {
self.put_slice(&n.to_be_bytes())
}
fn put_u128_le(&mut self, n: u128) {
self.put_slice(&n.to_le_bytes())
}
fn put_i128(&mut self, n: i128) {
self.put_slice(&n.to_be_bytes())
}
fn put_i128_le(&mut self, n: i128) {
self.put_slice(&n.to_le_bytes())
}
fn put_uint(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
fn put_uint_le(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
fn put_int(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
fn put_int_le(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
fn put_f32(&mut self, n: f32) {
self.put_u32(n.to_bits());
}
fn put_f32_le(&mut self, n: f32) {
self.put_u32_le(n.to_bits());
}
fn put_f64(&mut self, n: f64) {
self.put_u64(n.to_bits());
}
fn put_f64_le(&mut self, n: f64) {
self.put_u64_le(n.to_bits());
}
}
macro_rules! deref_forward_bufmut {
() => {
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
(**self).bytes_mut()
}
#[cfg(feature = "std")]
fn bytes_vectored_mut<'b>(&'b mut self, dst: &mut [IoSliceMut<'b>]) -> usize {
(**self).bytes_vectored_mut(dst)
}
unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt)
}
fn put_slice(&mut self, src: &[u8]) {
(**self).put_slice(src)
}
fn put_u8(&mut self, n: u8) {
(**self).put_u8(n)
}
fn put_i8(&mut self, n: i8) {
(**self).put_i8(n)
}
fn put_u16(&mut self, n: u16) {
(**self).put_u16(n)
}
fn put_u16_le(&mut self, n: u16) {
(**self).put_u16_le(n)
}
fn put_i16(&mut self, n: i16) {
(**self).put_i16(n)
}
fn put_i16_le(&mut self, n: i16) {
(**self).put_i16_le(n)
}
fn put_u32(&mut self, n: u32) {
(**self).put_u32(n)
}
fn put_u32_le(&mut self, n: u32) {
(**self).put_u32_le(n)
}
fn put_i32(&mut self, n: i32) {
(**self).put_i32(n)
}
fn put_i32_le(&mut self, n: i32) {
(**self).put_i32_le(n)
}
fn put_u64(&mut self, n: u64) {
(**self).put_u64(n)
}
fn put_u64_le(&mut self, n: u64) {
(**self).put_u64_le(n)
}
fn put_i64(&mut self, n: i64) {
(**self).put_i64(n)
}
fn put_i64_le(&mut self, n: i64) {
(**self).put_i64_le(n)
}
};
}
impl<T: BufMut + ?Sized> BufMut for &mut T {
deref_forward_bufmut!();
}
impl<T: BufMut + ?Sized> BufMut for Box<T> {
deref_forward_bufmut!();
}
impl BufMut for &mut [u8] {
#[inline]
fn remaining_mut(&self) -> usize {
self.len()
}
#[inline]
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
unsafe { mem::transmute(&mut **self) }
}
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b;
}
}
impl BufMut for Vec<u8> {
#[inline]
fn remaining_mut(&self) -> usize {
usize::MAX - self.len()
}
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
let len = self.len();
let remaining = self.capacity() - len;
assert!(
cnt <= remaining,
"cannot advance past `remaining_mut`: {:?} <= {:?}",
cnt,
remaining
);
self.set_len(len + cnt);
}
#[inline]
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
use core::slice;
if self.capacity() == self.len() {
self.reserve(64); }
let cap = self.capacity();
let len = self.len();
let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
unsafe { &mut slice::from_raw_parts_mut(ptr, cap)[len..] }
}
fn put<T: super::Buf>(&mut self, mut src: T)
where
Self: Sized,
{
self.reserve(src.remaining());
while src.has_remaining() {
let l;
{
let s = src.bytes();
l = s.len();
self.extend_from_slice(s);
}
src.advance(l);
}
}
fn put_slice(&mut self, src: &[u8]) {
self.extend_from_slice(src);
}
}
fn _assert_trait_object(_b: &dyn BufMut) {}
#[repr(transparent)]
#[cfg(feature = "std")]
pub struct IoSliceMut<'a>(std::io::IoSliceMut<'a>);
#[cfg(feature = "std")]
impl fmt::Debug for IoSliceMut<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IoSliceMut")
.field("len", &self.0.len())
.finish()
}
}
#[cfg(feature = "std")]
impl<'a> From<&'a mut [u8]> for IoSliceMut<'a> {
fn from(buf: &'a mut [u8]) -> IoSliceMut<'a> {
IoSliceMut(std::io::IoSliceMut::new(buf))
}
}
#[cfg(feature = "std")]
impl<'a> From<&'a mut [MaybeUninit<u8>]> for IoSliceMut<'a> {
fn from(buf: &'a mut [MaybeUninit<u8>]) -> IoSliceMut<'a> {
IoSliceMut(std::io::IoSliceMut::new(unsafe {
mem::transmute::<&'a mut [MaybeUninit<u8>], &'a mut [u8]>(buf)
}))
}
}