use crate::BufFactory;
use crate::Error;
use crate::Result;
use std::collections::VecDeque;
#[derive(Default)]
pub struct DatagramQueue<F: BufFactory> {
queue: VecDeque<F::DgramBuf>,
queue_max_len: usize,
queue_bytes_size: usize,
}
impl<F: BufFactory> DatagramQueue<F> {
pub fn new(queue_max_len: usize) -> Self {
DatagramQueue {
queue: VecDeque::new(),
queue_bytes_size: 0,
queue_max_len,
}
}
pub fn push(&mut self, data: F::DgramBuf) -> Result<()> {
if self.is_full() {
return Err(Error::Done);
}
self.queue_bytes_size += data.as_ref().len();
self.queue.push_back(data);
Ok(())
}
pub fn peek_front_len(&self) -> Option<usize> {
self.queue.front().map(|d| d.as_ref().len())
}
pub fn peek_front_bytes(&self, buf: &mut [u8], len: usize) -> Result<usize> {
match self.queue.front() {
Some(d) => {
let len = std::cmp::min(len, d.as_ref().len());
if buf.len() < len {
return Err(Error::BufferTooShort);
}
buf[..len].copy_from_slice(&d.as_ref()[..len]);
Ok(len)
},
None => Err(Error::Done),
}
}
pub fn pop(&mut self) -> Option<F::DgramBuf> {
if let Some(d) = self.queue.pop_front() {
self.queue_bytes_size =
self.queue_bytes_size.saturating_sub(d.as_ref().len());
return Some(d);
}
None
}
pub fn has_pending(&self) -> bool {
!self.queue.is_empty()
}
pub fn purge<FN: Fn(&[u8]) -> bool>(&mut self, f: FN) {
self.queue.retain(|d| !f(d.as_ref()));
self.queue_bytes_size = self
.queue
.iter()
.fold(0, |total, d| total + d.as_ref().len());
}
pub fn is_full(&self) -> bool {
self.len() == self.queue_max_len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn len(&self) -> usize {
self.queue.len()
}
pub fn byte_size(&self) -> usize {
self.queue_bytes_size
}
}