use crossbeam::queue::ArrayQueue;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::sync::Arc;
use crate::net::message::{Message, MessageBody};
use crate::net::message::MessageHandler;
use crate::net::Connection;
#[derive(Debug)]
pub struct MessageQueueFull {}
impl Display for MessageQueueFull {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Queue full")
}
}
impl Error for MessageQueueFull {}
pub struct MessageQueue<M>
where
M: MessageBody + Send + Sync + 'static,
{
inner: ArrayQueue<(Connection, Message<M>)>,
}
impl<M> MessageQueue<M>
where
M: MessageBody + Send + Sync + 'static,
{
#[inline]
pub fn new(cap: usize) -> Arc<Self> {
Arc::new(Self {
inner: ArrayQueue::new(cap),
})
}
#[inline]
pub fn pop(&self) -> Option<(Connection, Message<M>)> {
self.inner.pop()
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[inline]
pub fn is_full(&self) -> bool {
self.inner.is_full()
}
#[inline]
pub fn len(&self) -> usize {
self.inner.len()
}
#[inline]
pub fn iter(&self) -> MessageQueueIter<'_, M> {
MessageQueueIter { queue: self }
}
}
impl<M> MessageHandler<M, MessageQueueFull> for MessageQueue<M>
where
M: MessageBody + Send + Sync + 'static,
{
#[inline]
fn handle(&self, connection: Connection, msg: Message<M>) -> Result<(), MessageQueueFull> {
self.inner.push((connection, msg))
.map_err(|_| MessageQueueFull {})
}
}
impl<'a, M> IntoIterator for &'a MessageQueue<M>
where
M: MessageBody + Send + Sync + 'static,
{
type Item = (Connection, Message<M>);
type IntoIter = MessageQueueIter<'a, M>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct MessageQueueIter<'a, M>
where
M: MessageBody + Send + Sync + 'static,
{
queue: &'a MessageQueue<M>,
}
impl<'a, M> Iterator for MessageQueueIter<'a, M>
where
M: MessageBody + Send + Sync + 'static,
{
type Item = (Connection, Message<M>);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.queue.pop()
}
}