use std::collections::VecDeque;
use std::net::SocketAddr;
use std::time::Instant;
#[derive(Debug, Clone)]
pub struct QueuedDatagram {
pub delivery_time: Instant,
pub payload: Vec<u8>,
pub src: SocketAddr,
pub dst: SocketAddr,
}
#[derive(Debug, Default)]
pub struct SimChannel {
queue: VecDeque<QueuedDatagram>,
}
impl SimChannel {
pub fn new() -> Self {
Self {
queue: VecDeque::new(),
}
}
pub fn push(&mut self, datagram: QueuedDatagram) {
let idx = self
.queue
.binary_search_by_key(&datagram.delivery_time, |d| d.delivery_time)
.unwrap_or_else(|x| x);
self.queue.insert(idx, datagram);
}
pub fn pop_ready(&mut self, now: Instant) -> Option<QueuedDatagram> {
if let Some(front) = self.queue.front() {
if front.delivery_time <= now {
return self.queue.pop_front();
}
}
None
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_sim_channel_ordering() {
let mut channel = SimChannel::new();
let now = Instant::now();
let src: SocketAddr = "127.0.0.1:1000".parse().unwrap();
let dst: SocketAddr = "127.0.0.1:2000".parse().unwrap();
channel.push(QueuedDatagram {
delivery_time: now + Duration::from_millis(20),
payload: vec![2],
src,
dst,
});
channel.push(QueuedDatagram {
delivery_time: now + Duration::from_millis(10),
payload: vec![1],
src,
dst,
});
assert!(channel.pop_ready(now).is_none());
assert!(channel.pop_ready(now + Duration::from_millis(15)).is_some());
assert!(channel.pop_ready(now + Duration::from_millis(15)).is_none());
let next = channel.pop_ready(now + Duration::from_millis(25)).unwrap();
assert_eq!(next.payload, vec![2]);
}
}