use std::collections::VecDeque;
use crate::{DeliveryPolicy, MessageDeliveryPolicy};
#[derive(Clone, Debug)]
pub struct Deque<T>
where
T: MessageDeliveryPolicy,
{
data: VecDeque<T>,
capacity: usize,
ordered: bool,
}
impl<T> Deque<T>
where
T: MessageDeliveryPolicy,
{
#[inline]
pub fn bounded(capacity: usize) -> Self {
Self {
data: VecDeque::with_capacity(capacity),
capacity,
ordered: false,
}
}
#[inline]
pub fn with_ordering(mut self, v: bool) -> Self {
self.ordered = v;
self
}
pub fn try_push(&mut self, value: T) -> Option<T> {
macro_rules! push {
() => {
self.data.push_back(value);
if self.ordered {
sort_by_priority(&mut self.data);
}
};
}
if value.is_delivery_policy_single() {
self.data.retain(|d| !d.eq_kind(&value));
}
if self.data.len() < self.capacity {
push!();
None
} else {
match value.delivery_policy() {
DeliveryPolicy::Always | DeliveryPolicy::Single => {
let mut entry_removed = false;
self.data.retain(|d| {
if entry_removed {
true
} else {
let to_remove = d.is_expired() || d.is_delivery_policy_optional();
if to_remove {
entry_removed = true;
false
} else {
true
}
}
});
if self.data.len() < self.capacity {
push!();
None
} else {
Some(value)
}
}
DeliveryPolicy::Optional | DeliveryPolicy::SingleOptional => None,
}
}
}
#[inline]
pub fn get(&mut self) -> Option<T> {
self.data.pop_front()
}
#[inline]
pub fn clear(&mut self) {
self.data.clear();
}
#[inline]
pub fn usage(&self) -> usize {
self.data.len()
}
#[inline]
pub fn is_full(&self) -> bool {
self.usage() == self.capacity
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
fn sort_by_priority<T: MessageDeliveryPolicy>(v: &mut VecDeque<T>) {
let mut n = v.len();
let mut swapped = true;
while swapped {
swapped = false;
for i in 1..n {
if v[i - 1].priority() > v[i].priority() {
v.swap(i - 1, i);
swapped = true;
}
}
n -= 1;
}
}