use std::io::Cursor;
use crate::{Encode, Error, FourCC, Result};
pub trait Buf {
fn remaining(&self) -> usize;
fn has_remaining(&self) -> bool {
self.remaining() > 0
}
fn slice(&self, size: usize) -> &[u8];
fn advance(&mut self, n: usize);
}
impl Buf for &[u8] {
fn remaining(&self) -> usize {
self.len()
}
fn slice(&self, size: usize) -> &[u8] {
self[..size].as_ref()
}
fn advance(&mut self, n: usize) {
*self = &self[n..];
}
}
impl<T: AsRef<[u8]>> Buf for Cursor<T> {
fn remaining(&self) -> usize {
self.get_ref().as_ref().len() - self.position() as usize
}
fn slice(&self, size: usize) -> &[u8] {
let pos = self.position() as usize;
self.get_ref().as_ref()[pos..pos + size].as_ref()
}
fn advance(&mut self, n: usize) {
self.set_position(self.position() + n as u64);
}
}
impl<T: Buf + ?Sized> Buf for &mut T {
fn remaining(&self) -> usize {
(**self).remaining()
}
fn slice(&self, size: usize) -> &[u8] {
(**self).slice(size)
}
fn advance(&mut self, n: usize) {
(**self).advance(n);
}
}
pub(crate) fn skip_trailing_padding<B: Buf>(buf: &mut B) {
let n = buf.remaining();
if n > 0 && n < 8 {
buf.advance(n);
}
}
#[cfg(feature = "bytes")]
impl Buf for bytes::Bytes {
fn remaining(&self) -> usize {
self.len()
}
fn slice(&self, size: usize) -> &[u8] {
&self[..size]
}
fn advance(&mut self, n: usize) {
bytes::Buf::advance(self, n);
}
}
pub trait BufMut {
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn append_slice(&mut self, val: &[u8]);
fn set_slice(&mut self, pos: usize, val: &[u8]);
fn encode_atom<F>(&mut self, kind: impl Into<FourCC>, f: F) -> Result<()>
where
Self: Sized,
F: FnOnce(&mut Self) -> Result<()>,
{
let kind = kind.into();
let start = self.len();
0u32.encode(self)?; kind.encode(self)?;
f(self)?;
let size: u32 = (self.len() - start)
.try_into()
.map_err(|_| Error::TooLarge(kind))?;
self.set_slice(start, &size.to_be_bytes());
Ok(())
}
}
impl BufMut for Vec<u8> {
fn len(&self) -> usize {
self.len()
}
fn append_slice(&mut self, v: &[u8]) {
self.extend_from_slice(v);
}
fn set_slice(&mut self, pos: usize, val: &[u8]) {
self[pos..pos + val.len()].copy_from_slice(val);
}
}
impl<T: BufMut + ?Sized> BufMut for &mut T {
fn len(&self) -> usize {
(**self).len()
}
fn append_slice(&mut self, v: &[u8]) {
(**self).append_slice(v);
}
fn set_slice(&mut self, pos: usize, val: &[u8]) {
(**self).set_slice(pos, val);
}
}
#[cfg(feature = "bytes")]
impl BufMut for bytes::BytesMut {
fn len(&self) -> usize {
self.len()
}
fn append_slice(&mut self, v: &[u8]) {
self.extend_from_slice(v);
}
fn set_slice(&mut self, pos: usize, val: &[u8]) {
self[pos..pos + val.len()].copy_from_slice(val);
}
}