use crate::{Consumer, GrantR, GrantW, Producer};
use crate::{
vusize::{decode_usize, decoded_len, encode_usize_to_slice, encoded_len},
Result,
};
use core::{
cmp::min,
ops::{Deref, DerefMut},
};
pub struct FrameProducer<'a, const N: usize> {
pub(crate) producer: Producer<'a, N>,
}
impl<'a, const N: usize> FrameProducer<'a, N> {
pub fn grant(&mut self, max_sz: usize) -> Result<FrameGrantW<'a, N>> {
let hdr_len = encoded_len(max_sz);
Ok(FrameGrantW {
grant_w: self.producer.grant_exact(max_sz + hdr_len)?,
hdr_len: hdr_len as u8,
})
}
}
pub struct FrameConsumer<'a, const N: usize> {
pub(crate) consumer: Consumer<'a, N>,
}
impl<'a, const N: usize> FrameConsumer<'a, N> {
pub fn read(&mut self) -> Option<FrameGrantR<'a, N>> {
let mut grant_r = self.consumer.read().ok()?;
let frame_len = decode_usize(&grant_r);
let hdr_len = decoded_len(grant_r[0]);
let total_len = frame_len + hdr_len;
let hdr_len = hdr_len as u8;
debug_assert!(grant_r.len() >= total_len);
grant_r.shrink(total_len);
Some(FrameGrantR { grant_r, hdr_len })
}
}
#[derive(Debug, PartialEq)]
pub struct FrameGrantW<'a, const N: usize> {
grant_w: GrantW<'a, N>,
hdr_len: u8,
}
#[derive(Debug, PartialEq)]
pub struct FrameGrantR<'a, const N: usize> {
grant_r: GrantR<'a, N>,
hdr_len: u8,
}
impl<'a, const N: usize> Deref for FrameGrantW<'a, N> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.grant_w.buf[self.hdr_len.into()..]
}
}
impl<'a, const N: usize> DerefMut for FrameGrantW<'a, N> {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.grant_w.buf[self.hdr_len.into()..]
}
}
impl<'a, const N: usize> Deref for FrameGrantR<'a, N> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.grant_r.buf[self.hdr_len.into()..]
}
}
impl<'a, const N: usize> DerefMut for FrameGrantR<'a, N> {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.grant_r.buf[self.hdr_len.into()..]
}
}
impl<'a, const N: usize> FrameGrantW<'a, N> {
pub fn commit(mut self, used: usize) {
let total_len = self.set_header(used);
self.grant_w.commit(total_len);
}
fn set_header(&mut self, used: usize) -> usize {
let grant_len = self.grant_w.len();
let hdr_len: usize = self.hdr_len.into();
let frame_len = min(used, grant_len - hdr_len);
let total_len = frame_len + hdr_len;
encode_usize_to_slice(frame_len, hdr_len, &mut self.grant_w[..hdr_len]);
total_len
}
pub fn to_commit(&mut self, amt: usize) {
if amt == 0 {
self.grant_w.to_commit(0);
} else {
let size = self.set_header(amt);
self.grant_w.to_commit(size);
}
}
}
impl<'a, const N: usize> FrameGrantR<'a, N> {
pub fn release(mut self) {
let len = self.grant_r.len();
self.grant_r.release_inner(len);
}
pub fn auto_release(&mut self, is_auto: bool) {
self.grant_r
.to_release(if is_auto { self.grant_r.len() } else { 0 });
}
}