plckit 0.1.2

Kit for PLCs and real-time micro-services
Documentation
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
    }
    /// Returns the value if data push failed
    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;
    }
}