use std::collections::BTreeMap;
use crate::{
connection::databuf::DataBuf, header::PackageId, record::DeliveryRecord, MAX_PACKAGE_SIZE,
};
pub(super) struct Pending {
ids: BTreeMap<PackageId, DeliveryRecord>,
buf: DataBuf,
}
impl Pending {
pub(super) fn new() -> Self {
Self {
ids: BTreeMap::new(),
buf: DataBuf::new(),
}
}
pub(super) fn store(&mut self, record: DeliveryRecord, data: &[u8]) {
assert!(record.header().reliability().is_ordered());
assert!(data.len() <= MAX_PACKAGE_SIZE);
let id = record.header().id();
let result = self.ids.insert(id, record);
assert!(result.is_none());
self.buf.push(id, data);
}
pub(super) fn pop_first(
&mut self,
bound: PackageId,
buf: &mut [u8],
) -> Option<(DeliveryRecord, usize)> {
match self.ids.first_entry() {
Some(entry) => {
if entry.key().cmp(&bound).is_lt() {
let id = *entry.key();
let record = entry.remove();
Some((record, self.buf.get_and_remove(id, buf).unwrap()))
} else {
None
}
}
None => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{header::PackageHeader, Peers, Reliability, MAX_PACKAGE_SIZE};
#[test]
fn test_pending() {
let pkg_a = DeliveryRecord::now(PackageHeader::new(
Reliability::SemiOrdered,
Peers::Server,
PackageId::from_bytes(&[0, 0, 18]),
));
let pkg_b = DeliveryRecord::now(PackageHeader::new(
Reliability::SemiOrdered,
Peers::Server,
PackageId::from_bytes(&[0, 0, 14]),
));
let pkg_c = DeliveryRecord::now(PackageHeader::new(
Reliability::SemiOrdered,
Peers::Server,
PackageId::from_bytes(&[0, 0, 22]),
));
let mut buf = [0u8; MAX_PACKAGE_SIZE];
let mut pending = Pending::new();
assert!(pending
.pop_first(PackageId::from_bytes(&[0, 0, 10]), &mut buf)
.is_none());
pending.store(pkg_a.clone(), &[4, 5, 6, 7]);
pending.store(pkg_b.clone(), &[1, 2, 3]);
pending.store(pkg_c.clone(), &[92, 86]);
assert!(pending
.pop_first(PackageId::from_bytes(&[0, 0, 10]), &mut buf)
.is_none());
assert_eq!(
pending
.pop_first(PackageId::from_bytes(&[0, 0, 20]), &mut buf)
.unwrap(),
(pkg_b, 3)
);
assert_eq!(&buf[..3], &[1, 2, 3]);
assert_eq!(
pending
.pop_first(PackageId::from_bytes(&[0, 0, 20]), &mut buf)
.unwrap(),
(pkg_a, 4)
);
assert_eq!(&buf[..4], &[4, 5, 6, 7]);
assert!(pending
.pop_first(PackageId::from_bytes(&[0, 0, 20]), &mut buf)
.is_none());
assert_eq!(
pending
.pop_first(PackageId::from_bytes(&[0, 0, 30]), &mut buf)
.unwrap(),
(pkg_c, 2)
);
assert_eq!(&buf[..2], &[92, 86]);
assert!(pending
.pop_first(PackageId::from_bytes(&[0, 0, 30]), &mut buf)
.is_none());
}
}