use super::bytes::{Bytes, BytesMut};
pub trait Buf {
fn remaining(&self) -> usize;
fn chunk(&self) -> &[u8];
fn advance(&mut self, cnt: usize);
fn has_remaining(&self) -> bool {
self.remaining() > 0
}
fn get_uint(&mut self, nbytes: usize) -> u64 {
assert!((1..=8).contains(&nbytes), "get_uint: nbytes must be 1..=8");
let mut out = [0u8; 8];
self.copy_to_slice(&mut out[8 - nbytes..]);
u64::from_be_bytes(out)
}
fn copy_to_slice(&mut self, dst: &mut [u8]) {
let mut filled = 0usize;
while filled < dst.len() {
let chunk = self.chunk();
debug_assert!(
!chunk.is_empty(),
"Buf impl violated contract: chunk() empty while remaining() > 0"
);
let take = (dst.len() - filled).min(chunk.len());
dst[filled..filled + take].copy_from_slice(&chunk[..take]);
self.advance(take);
filled += take;
}
}
fn get_u8(&mut self) -> u8 {
let mut buf = [0u8; 1];
self.copy_to_slice(&mut buf);
buf[0]
}
fn get_u16(&mut self) -> u16 {
let mut buf = [0u8; 2];
self.copy_to_slice(&mut buf);
u16::from_be_bytes(buf)
}
fn get_i16(&mut self) -> i16 {
let mut buf = [0u8; 2];
self.copy_to_slice(&mut buf);
i16::from_be_bytes(buf)
}
fn get_u32(&mut self) -> u32 {
let mut buf = [0u8; 4];
self.copy_to_slice(&mut buf);
u32::from_be_bytes(buf)
}
fn get_i32(&mut self) -> i32 {
let mut buf = [0u8; 4];
self.copy_to_slice(&mut buf);
i32::from_be_bytes(buf)
}
fn get_u64(&mut self) -> u64 {
let mut buf = [0u8; 8];
self.copy_to_slice(&mut buf);
u64::from_be_bytes(buf)
}
}
pub trait BufMut {
fn remaining_mut(&self) -> usize;
fn put_slice(&mut self, src: &[u8]);
fn put_u8(&mut self, n: u8) {
self.put_slice(&[n]);
}
fn put_u16(&mut self, n: u16) {
self.put_slice(&n.to_be_bytes());
}
fn put_i16(&mut self, n: i16) {
self.put_slice(&n.to_be_bytes());
}
fn put_u32(&mut self, n: u32) {
self.put_slice(&n.to_be_bytes());
}
fn put_i32(&mut self, n: i32) {
self.put_slice(&n.to_be_bytes());
}
fn put_u64(&mut self, n: u64) {
self.put_slice(&n.to_be_bytes());
}
fn put_uint(&mut self, n: u64, nbytes: usize) {
assert!((1..=8).contains(&nbytes), "put_uint: nbytes must be 1..=8");
let bytes = n.to_be_bytes();
self.put_slice(&bytes[8 - nbytes..]);
}
fn put<T: Buf>(&mut self, mut src: T) {
while src.remaining() > 0 {
let chunk = src.chunk();
let len = chunk.len();
self.put_slice(chunk);
src.advance(len);
}
}
}
impl Buf for &[u8] {
fn remaining(&self) -> usize {
self.len()
}
fn chunk(&self) -> &[u8] {
self
}
fn advance(&mut self, cnt: usize) {
*self = &self[cnt..];
}
fn copy_to_slice(&mut self, dst: &mut [u8]) {
let n = dst.len();
dst.copy_from_slice(&self[..n]);
*self = &self[n..];
}
fn get_u8(&mut self) -> u8 {
let v = self[0];
*self = &self[1..];
v
}
fn get_u32(&mut self) -> u32 {
let v = u32::from_be_bytes(self[..4].try_into().unwrap());
*self = &self[4..];
v
}
}
impl<T: AsRef<[u8]>> Buf for std::io::Cursor<T> {
fn remaining(&self) -> usize {
let pos = self.position() as usize;
let total = self.get_ref().as_ref().len();
total.saturating_sub(pos)
}
fn chunk(&self) -> &[u8] {
let pos = self.position() as usize;
let buf = self.get_ref().as_ref();
let pos = pos.min(buf.len());
&buf[pos..]
}
fn advance(&mut self, cnt: usize) {
let new = self.position().saturating_add(cnt as u64);
self.set_position(new);
}
}
impl Buf for Bytes {
fn remaining(&self) -> usize {
self.len()
}
fn chunk(&self) -> &[u8] {
self.as_slice()
}
fn advance(&mut self, cnt: usize) {
Self::advance(self, cnt);
}
}
impl BufMut for Vec<u8> {
fn remaining_mut(&self) -> usize {
usize::MAX - self.len()
}
fn put_slice(&mut self, src: &[u8]) {
self.extend_from_slice(src);
}
}
impl BufMut for BytesMut {
fn remaining_mut(&self) -> usize {
usize::MAX - self.len()
}
fn put_slice(&mut self, src: &[u8]) {
self.extend_from_slice(src);
}
}
impl BufMut for &mut [u8] {
fn remaining_mut(&self) -> usize {
self.len()
}
fn put_slice(&mut self, src: &[u8]) {
let n = src.len();
let (head, tail) = std::mem::take(self).split_at_mut(n);
head.copy_from_slice(src);
*self = tail;
}
}
impl<T: BufMut + ?Sized> BufMut for &mut T {
fn remaining_mut(&self) -> usize {
(**self).remaining_mut()
}
fn put_slice(&mut self, src: &[u8]) {
(**self).put_slice(src)
}
}
impl<T: Buf + ?Sized> Buf for &mut T {
fn remaining(&self) -> usize {
(**self).remaining()
}
fn chunk(&self) -> &[u8] {
(**self).chunk()
}
fn advance(&mut self, cnt: usize) {
(**self).advance(cnt)
}
}