use crate::BufFactory;
use crate::Error;
use crate::Result;
use std::collections::VecDeque;
#[derive(Default)]
pub struct DatagramQueue<F: BufFactory> {
queue: Option<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: None,
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
.get_or_insert_with(Default::default)
.push_back(data);
Ok(())
}
pub fn peek_front_len(&self) -> Option<usize> {
self.queue
.as_ref()
.and_then(|q| q.front().map(|d| d.as_ref().len()))
}
pub fn peek_front_bytes(&self, buf: &mut [u8], len: usize) -> Result<usize> {
match self.queue.as_ref().and_then(|q| q.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.as_mut().and_then(|q| q.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.as_ref().map(|q| q.is_empty()).unwrap_or(true)
}
pub fn purge<FN: Fn(&[u8]) -> bool>(&mut self, f: FN) {
if let Some(q) = self.queue.as_mut() {
q.retain(|d| !f(d.as_ref()));
self.queue_bytes_size =
q.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.as_ref().map(|q| q.len()).unwrap_or(0)
}
pub fn byte_size(&self) -> usize {
self.queue_bytes_size
}
}