use std::{cmp, mem, ptr};
use super::{UninitSlice, Writer};
pub trait BufMut {
fn remaining_mut(&self) -> usize;
#[allow(clippy::missing_safety_doc)]
unsafe fn advance_mut(&mut self, cnt: usize);
#[inline]
fn has_remaining_mut(&self) -> bool {
self.remaining_mut() > 0
}
fn chunk_mut(&mut self) -> &mut UninitSlice;
fn put<T: super::Buf>(&mut self, mut src: T)
where
Self: Sized,
{
assert!(self.remaining_mut() >= src.remaining());
while src.has_remaining() {
let s = src.chunk();
let d = self.chunk_mut();
let l = cmp::min(s.len(), d.len());
unsafe {
ptr::copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), 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");
while off < src.len() {
let 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(), cnt);
off += cnt;
}
unsafe {
self.advance_mut(cnt);
}
}
}
#[inline]
fn put_u8(&mut self, n: u8) {
let src = [n];
self.put_slice(&src);
}
fn put_i8(&mut self, n: i8) {
self.put_slice(&[n as u8]);
}
#[inline]
fn put_u16(&mut self, n: u16) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_u16_le(&mut self, n: u16) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_i16(&mut self, n: i16) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_i16_le(&mut self, n: i16) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_u32(&mut self, n: u32) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_u32_le(&mut self, n: u32) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_i32(&mut self, n: i32) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_i32_le(&mut self, n: i32) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_u64(&mut self, n: u64) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_u64_le(&mut self, n: u64) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_i64(&mut self, n: i64) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_i64_le(&mut self, n: i64) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_u128(&mut self, n: u128) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_u128_le(&mut self, n: u128) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_i128(&mut self, n: i128) {
self.put_slice(&n.to_be_bytes());
}
#[inline]
fn put_i128_le(&mut self, n: i128) {
self.put_slice(&n.to_le_bytes());
}
#[inline]
fn put_uint(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
#[inline]
fn put_uint_le(&mut self, n: u64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
#[inline]
fn put_int(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_be_bytes()[mem::size_of_val(&n) - nbytes..]);
}
#[inline]
fn put_int_le(&mut self, n: i64, nbytes: usize) {
self.put_slice(&n.to_le_bytes()[0..nbytes]);
}
#[inline]
fn put_f32(&mut self, n: f32) {
self.put_u32(n.to_bits());
}
#[inline]
fn put_f32_le(&mut self, n: f32) {
self.put_u32_le(n.to_bits());
}
#[inline]
fn put_f64(&mut self, n: f64) {
self.put_u64(n.to_bits());
}
#[inline]
fn put_f64_le(&mut self, n: f64) {
self.put_u64_le(n.to_bits());
}
fn writer(self) -> Writer<Self>
where
Self: Sized,
{
Writer::new(self)
}
}
impl<T: BufMut + ?Sized> BufMut for &mut T {
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
fn chunk_mut(&mut self) -> &mut UninitSlice {
(**self).chunk_mut()
}
unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt);
}
}
impl<T: BufMut + ?Sized> BufMut for Box<T> {
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
fn chunk_mut(&mut self) -> &mut UninitSlice {
(**self).chunk_mut()
}
unsafe fn advance_mut(&mut self, cnt: usize) {
(**self).advance_mut(cnt);
}
}
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;
if cnt > remaining {
self.reserve(cnt);
}
self.set_len(len + cnt);
}
#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice {
if self.capacity() == self.len() {
self.reserve(64); }
let cap = self.capacity();
let len = self.len();
let ptr = self.as_mut_ptr();
unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, cap)[len..] }
}
}
impl BufMut for &mut [u8] {
#[inline]
fn remaining_mut(&self) -> usize {
self.len()
}
#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice {
unsafe { &mut *(ptr::from_mut::<[u8]>(*self) as *mut _) }
}
#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
let (_, b) = core::mem::take(self).split_at_mut(cnt);
*self = b;
}
#[inline]
fn put_slice(&mut self, src: &[u8]) {
self[..src.len()].copy_from_slice(src);
unsafe {
self.advance_mut(src.len());
}
}
}
fn _assert_trait_object(_b: &dyn BufMut) {}
#[cfg(test)]
#[allow(unused_allocation, warnings)]
mod tests {
use super::*;
use crate::BytesMut;
#[test]
#[allow(clippy::needless_borrow, clippy::too_many_lines)]
fn buf_mut_tests() {
let mut buf = vec![];
buf.put_u8(0x01);
assert_eq!(buf, b"\x01");
assert_eq!(buf.remaining_mut(), usize::MAX - 1);
assert_eq!((&buf).remaining_mut(), usize::MAX - 1);
assert_eq!(Box::new(buf).remaining_mut(), usize::MAX - 1);
let mut buf = [b'1'; 10];
let mut b = buf.as_mut();
assert_eq!(b.remaining_mut(), 10);
assert!(b.has_remaining_mut());
b.put_slice(b"123");
assert_eq!(&buf[..], b"1231111111");
let mut b: &mut [u8] = buf.as_mut();
let chunk = b.chunk_mut();
chunk.write_byte(0, b'9');
assert_eq!(&buf[..], b"9231111111");
let mut b = buf.as_mut();
let chunk = b.chunk_mut();
chunk.copy_from_slice(b"0000000000");
assert_eq!(&buf[..], b"0000000000");
let mut b = buf.as_mut();
assert_eq!(format!("{:?}", b.chunk_mut()), "UninitSlice[...]");
let b = buf.as_mut();
let mut bb = Box::new(b);
unsafe { bb.advance_mut(1) };
let chunk = bb.chunk_mut();
chunk.copy_from_slice(b"111111111");
assert_eq!(&buf[..], b"0111111111");
let mut buf = BytesMut::new();
buf.put_u8(0x01);
assert_eq!(buf, b"\x01"[..]);
let mut buf = BytesMut::new();
buf.put_u8(0x01);
assert_eq!(buf, b"\x01"[..]);
let mut buf = vec![];
buf.put_i8(0x01);
assert_eq!(buf, b"\x01");
let mut buf = BytesMut::new();
buf.put_i8(0x01);
assert_eq!(buf, b"\x01"[..]);
let mut buf = BytesMut::new();
buf.put_i8(0x01);
assert_eq!(buf, b"\x01"[..]);
assert_eq!((&mut buf).remaining_mut(), 107);
let chunk = (&mut buf).chunk_mut();
chunk.write_byte(0, b'9');
unsafe { (&mut buf).advance_mut(1) };
assert_eq!((&mut buf).remaining_mut(), 106);
let mut buf = vec![];
buf.put_i16(0x0809);
assert_eq!(buf, b"\x08\x09");
let mut buf = vec![];
buf.put_i16_le(0x0809);
assert_eq!(buf, b"\x09\x08");
let mut buf = vec![];
buf.put_u32(0x0809_A0A1);
assert_eq!(buf, b"\x08\x09\xA0\xA1");
let mut buf = vec![];
buf.put_i32(0x0809_A0A1);
assert_eq!(buf, b"\x08\x09\xA0\xA1");
let mut buf = vec![];
buf.put_i32_le(0x0809_A0A1);
assert_eq!(buf, b"\xA1\xA0\x09\x08");
let mut buf = vec![];
buf.put_u64(0x0102_0304_0506_0708);
assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
let mut buf = vec![];
buf.put_u64_le(0x0102_0304_0506_0708);
assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
let mut buf = vec![];
buf.put_i64(0x0102_0304_0506_0708);
assert_eq!(buf, b"\x01\x02\x03\x04\x05\x06\x07\x08");
let mut buf = vec![];
buf.put_i64_le(0x0102_0304_0506_0708);
assert_eq!(buf, b"\x08\x07\x06\x05\x04\x03\x02\x01");
let mut buf = vec![];
buf.put_u128(0x0102_0304_0506_0708_0910_1112_1314_1516);
assert_eq!(
buf,
b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
);
let mut buf = vec![];
buf.put_u128_le(0x0102_0304_0506_0708_0910_1112_1314_1516);
assert_eq!(
buf,
b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01"
);
let mut buf = vec![];
buf.put_i128(0x0102_0304_0506_0708_0910_1112_1314_1516);
assert_eq!(
buf,
b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16"
);
let mut buf = vec![];
buf.put_i128_le(0x0102_0304_0506_0708_0910_1112_1314_1516);
assert_eq!(
buf,
b"\x16\x15\x14\x13\x12\x11\x10\x09\x08\x07\x06\x05\x04\x03\x02\x01"
);
let mut buf = vec![];
buf.put_uint(0x01_0203, 3);
assert_eq!(buf, b"\x01\x02\x03");
let mut buf = vec![];
buf.put_uint_le(0x01_0203, 3);
assert_eq!(buf, b"\x03\x02\x01");
let mut buf = vec![];
buf.put_int(0x01_0203, 3);
assert_eq!(buf, b"\x01\x02\x03");
let mut buf = vec![];
buf.put_int_le(0x01_0203, 3);
assert_eq!(buf, b"\x03\x02\x01");
let mut buf = vec![];
buf.put_f32(1.2f32);
assert_eq!(buf, b"\x3F\x99\x99\x9A");
let mut buf = vec![];
buf.put_f32_le(1.2f32);
assert_eq!(buf, b"\x9A\x99\x99\x3F");
let mut buf = vec![];
buf.put_f64(1.2f64);
assert_eq!(buf, b"\x3F\xF3\x33\x33\x33\x33\x33\x33");
let mut buf = vec![];
buf.put_f64_le(1.2f64);
assert_eq!(buf, b"\x33\x33\x33\x33\x33\x33\xF3\x3F");
}
}