use core::fmt;
use core::ops::{Deref, DerefMut};
use crate::{AsPixel, Pixel};
use crate::buf::{Buffer, buf};
use zerocopy::{AsBytes, FromBytes};
pub struct Rec<P: AsBytes + FromBytes> {
inner: Buffer,
length: usize,
pixel: Pixel<P>,
}
pub struct ReuseError {
requested: Option<usize>,
capacity: usize,
}
impl<P: AsBytes + FromBytes> Rec<P> {
pub fn new(count: usize) -> Self where P: AsPixel {
Self::new_for_pixel(P::pixel(), count)
}
pub fn new_for_pixel(pixel: Pixel<P>, count: usize) -> Self {
Self::bytes_for_pixel(pixel, mem_size(pixel, count))
}
pub fn bytes_for_pixel(pixel: Pixel<P>, mem_size: usize) -> Self {
Rec {
inner: Buffer::new(mem_size),
length: mem_size,
pixel,
}
}
pub fn resize(&mut self, count: usize) {
self.resize_bytes(mem_size(self.pixel, count))
}
pub fn resize_bytes(&mut self, bytes: usize) {
self.inner.grow_to(bytes);
self.length = bytes;
}
pub fn reuse(&mut self, count: usize) -> Result<(), ReuseError> {
let bytes = count
.checked_mul(self.pixel.size())
.ok_or_else(|| ReuseError {
requested: None,
capacity: self.byte_capacity(),
})?;
self.reuse_bytes(bytes)
}
pub fn reuse_bytes(&mut self, bytes: usize) -> Result<(), ReuseError> {
if bytes > self.byte_capacity() {
return Err(ReuseError {
requested: Some(bytes),
capacity: self.capacity(),
})
}
Ok(self.resize_bytes(bytes))
}
pub fn shrink_to_fit(&mut self) {
let exact_size = mem_size(self.pixel, self.len());
self.inner.resize_to(exact_size);
self.length = exact_size;
}
pub fn as_slice(&self) -> &[P] {
self.buf().as_pixels(self.pixel)
}
pub fn as_mut_slice(&mut self) -> &mut [P] {
let pixel = self.pixel;
self.buf_mut().as_mut_pixels(pixel)
}
pub fn len(&self) -> usize {
self.as_slice().len()
}
pub fn capacity(&self) -> usize {
self.inner.capacity() / self.pixel.size()
}
pub fn as_bytes(&self) -> &[u8] {
self.buf().as_bytes()
}
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
self.buf_mut().as_bytes_mut()
}
pub fn byte_len(&self) -> usize {
self.as_bytes().len()
}
pub fn byte_capacity(&self) -> usize {
self.inner.capacity()
}
pub fn reinterpret<Q>(self) -> Rec<Q>
where Q: AsPixel + AsBytes + FromBytes
{
self.reinterpret_to(Q::pixel())
}
pub fn reinterpret_to<Q>(self, pixel: Pixel<Q>) -> Rec<Q>
where Q: AsBytes + FromBytes
{
Rec {
inner: self.inner,
length: self.length,
pixel,
}
}
fn buf(&self) -> &buf {
&self.inner[..self.length]
}
fn buf_mut(&mut self) -> &mut buf {
&mut self.inner[..self.length]
}
}
fn mem_size<P>(pixel: Pixel<P>, count: usize) -> usize {
pixel.size().checked_mul(count).unwrap_or_else(
|| panic!("Requested count overflows memory size"))
}
impl<P: AsBytes + FromBytes> Deref for Rec<P> {
type Target = [P];
fn deref(&self) -> &[P] {
self.as_slice()
}
}
impl<P: AsBytes + FromBytes> DerefMut for Rec<P> {
fn deref_mut(&mut self) -> &mut [P] {
self.as_mut_slice()
}
}
impl fmt::Debug for ReuseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.requested {
None => {
write!(f, "Buffer reuse failed: Bytes count can not be expressed")
},
Some(requested) => {
write!(f, "Buffer reuse failed: {} bytes requested, only {} available",
requested, self.capacity)
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resize() {
let mut buffer: Rec<u8> = Rec::new(0);
assert_eq!(buffer.capacity(), 0);
assert_eq!(buffer.len(), 0);
buffer.resize(4);
assert!(buffer.capacity() >= 4);
assert_eq!(buffer.len(), 4);
buffer.resize(2);
assert!(buffer.capacity() >= 2);
assert_eq!(buffer.len(), 2);
buffer.resize(0);
buffer.shrink_to_fit();
assert_eq!(buffer.capacity(), 0);
assert_eq!(buffer.len(), 0);
}
}