use super::sphinx::{Packet, PeerId};
use std::{
cmp::Ordering,
collections::{BinaryHeap, VecDeque},
time::Instant,
};
pub struct AddressedPacket {
pub peer_id: PeerId,
pub packet: Box<Packet>,
}
struct ForwardPacket {
deadline: Instant,
packet: AddressedPacket,
}
impl PartialEq for ForwardPacket {
fn eq(&self, other: &Self) -> bool {
self.deadline == other.deadline
}
}
impl Eq for ForwardPacket {}
impl PartialOrd for ForwardPacket {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ForwardPacket {
fn cmp(&self, other: &Self) -> Ordering {
self.deadline.cmp(&other.deadline).reverse()
}
}
pub struct ForwardPacketQueue {
capacity: usize,
queue: BinaryHeap<ForwardPacket>,
}
impl ForwardPacketQueue {
pub fn new(capacity: usize) -> Self {
Self { capacity, queue: BinaryHeap::with_capacity(capacity) }
}
pub fn next_deadline(&self) -> Option<Instant> {
self.queue.peek().map(|packet| packet.deadline)
}
pub fn has_space(&self) -> bool {
self.queue.len() < self.capacity
}
pub fn insert(&mut self, deadline: Instant, packet: AddressedPacket) -> bool {
debug_assert!(self.has_space());
let prev_deadline = self.next_deadline();
self.queue.push(ForwardPacket { deadline, packet });
self.next_deadline() != prev_deadline
}
pub fn pop(&mut self) -> Option<AddressedPacket> {
self.queue.pop().map(|packet| packet.packet)
}
}
#[derive(Clone, Copy, Debug)]
pub struct AuthoredPacketQueueConfig {
pub capacity: usize,
pub multiple_messages: bool,
}
pub enum CheckSpaceErr {
Capacity,
Len,
}
pub struct AuthoredPacketQueue {
config: AuthoredPacketQueueConfig,
queue: VecDeque<AddressedPacket>,
}
impl AuthoredPacketQueue {
pub fn new(config: AuthoredPacketQueueConfig) -> Self {
Self { config, queue: VecDeque::with_capacity(config.capacity) }
}
pub fn len(&self) -> usize {
self.queue.len()
}
pub fn check_space(&self, num_packets: usize) -> Result<(), CheckSpaceErr> {
let Some(mut max_len) = self.config.capacity.checked_sub(num_packets) else {
return Err(CheckSpaceErr::Capacity)
};
if !self.config.multiple_messages {
max_len = 0;
}
if self.queue.len() > max_len {
Err(CheckSpaceErr::Len)
} else {
Ok(())
}
}
pub fn push(&mut self, packet: AddressedPacket) {
debug_assert!(self.queue.len() < self.config.capacity);
self.queue.push_back(packet);
}
pub fn pop(&mut self) -> (Option<AddressedPacket>, bool) {
let packet = self.queue.pop_front();
let space = packet.is_some() && (self.config.multiple_messages || self.queue.is_empty());
(packet, space)
}
}