use std::convert::TryInto;
pub trait VecLike {
fn as_mut_bytes(&mut self) -> &mut [u8];
unsafe fn reserve(&mut self, additional: usize) -> Result<(), BufferTooShortError>;
unsafe fn set_len(&mut self, new_len: usize);
}
#[derive(Debug, thiserror::Error)]
#[error("Cannot reserve buffer capacity to {requested_capacity}")]
pub struct BufferTooShortError {
pub requested_capacity: usize,
}
impl VecLike for Vec<u8> {
fn as_mut_bytes(&mut self) -> &mut [u8] {
self.as_mut_slice()
}
unsafe fn reserve(&mut self, additional: usize) -> Result<(), BufferTooShortError> {
Vec::reserve(self, additional);
Ok(())
}
unsafe fn set_len(&mut self, new_len: usize) {
Vec::set_len(self, new_len)
}
}
impl<'a> VecLike for std::io::Cursor<&'a mut [u8]> {
fn as_mut_bytes(&mut self) -> &mut [u8] {
let pos = self.position().try_into().unwrap_or(usize::max_value());
let bytes = self.get_mut();
let pos = pos.min(bytes.len());
&mut bytes[..pos]
}
unsafe fn reserve(&mut self, additional: usize) -> Result<(), BufferTooShortError> {
let pos = self.position().try_into().unwrap_or(usize::max_value());
let reserved = pos.saturating_add(additional);
if reserved >= self.get_ref().len() {
Ok(())
} else {
Err(BufferTooShortError {
requested_capacity: reserved,
})
}
}
unsafe fn set_len(&mut self, new_len: usize) {
self.set_position(new_len as u64)
}
}
#[cfg(feature = "bytes")]
impl VecLike for bytes::BytesMut {
fn as_mut_bytes(&mut self) -> &mut [u8] {
&mut self[..]
}
unsafe fn reserve(&mut self, additional: usize) -> Result<(), BufferTooShortError> {
bytes::BytesMut::reserve(self, additional);
Ok(())
}
unsafe fn set_len(&mut self, new_len: usize) {
bytes::BytesMut::set_len(self, new_len)
}
}