use crate::{
ack::Settings,
frame::ack,
interval_set::{IntervalSet, RangeInclusiveIter},
packet::number::{PacketNumber, PacketNumberRange},
varint::VarInt,
};
use core::{
convert::TryInto,
num::NonZeroUsize,
ops::{Bound, Deref, DerefMut, RangeInclusive},
};
#[derive(Clone, Debug)]
pub struct Ranges(IntervalSet<PacketNumber>);
impl Default for Ranges {
#[inline]
fn default() -> Self {
Self::new(Settings::default().ack_ranges_limit as usize)
}
}
impl Ranges {
#[inline]
pub fn new(limit: usize) -> Self {
let limit = NonZeroUsize::new(limit).expect("limit should be nonzero");
Self(IntervalSet::with_limit(limit))
}
#[inline]
pub fn insert_packet_number_range(&mut self, pn_range: PacketNumberRange) -> Result<(), Error> {
let interval = (
Bound::Included(pn_range.start()),
Bound::Included(pn_range.end()),
);
if self.0.insert(interval).is_ok() {
return Ok(());
}
match self.0.pop_min() {
Some(min) => {
if min < pn_range.start() {
let insert_res = self.0.insert(interval);
debug_assert!(
insert_res.is_ok(),
"min range was removed, so it should be possible to insert another range",
);
insert_res.map_err(|_| Error::RangeInsertionFailed {
min: pn_range.start(),
max: pn_range.end(),
})?;
Err(Error::LowestRangeDropped {
min: min.start_inclusive(),
max: min.end_inclusive(),
})
} else {
let _ = self.0.insert_front(min);
Err(Error::RangeInsertionFailed {
min: pn_range.start(),
max: pn_range.end(),
})
}
}
None => {
debug_assert!(
false,
"IntervalSet should have capacity and return lowest entry"
);
Err(Error::RangeInsertionFailed {
min: pn_range.start(),
max: pn_range.end(),
})
}
}
}
#[inline]
pub fn insert_packet_number(&mut self, packet_number: PacketNumber) -> Result<(), Error> {
self.insert_packet_number_range(PacketNumberRange::new(packet_number, packet_number))
}
#[inline]
pub fn spread(&self) -> usize {
match (self.min_value(), self.max_value()) {
(Some(min), Some(max)) => {
let min = PacketNumber::as_varint(min);
let max = PacketNumber::as_varint(max);
(max - min).try_into().unwrap_or(usize::MAX)
}
_ => 0,
}
}
}
type Iter<'a> = core::iter::Map<
core::iter::Rev<RangeInclusiveIter<'a, PacketNumber>>,
fn(RangeInclusive<PacketNumber>) -> RangeInclusive<VarInt>,
>;
impl<'a> ack::AckRanges for &'a Ranges {
type Iter = Iter<'a>;
#[inline]
fn ack_ranges(&self) -> Self::Iter {
self.0.inclusive_ranges().rev().map(|range| {
let (start, end) = range.into_inner();
PacketNumber::as_varint(start)..=PacketNumber::as_varint(end)
})
}
}
impl Deref for Ranges {
type Target = IntervalSet<PacketNumber>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Ranges {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Error {
RangeInsertionFailed {
min: PacketNumber,
max: PacketNumber,
},
LowestRangeDropped {
min: PacketNumber,
max: PacketNumber,
},
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
packet::number::{testing::iter as packet_numbers_iter, PacketNumberSpace},
varint,
};
use bolero::check;
#[test]
fn insert_value_test() {
let mut ack_ranges = Ranges::new(3);
let mut packet_numbers = packet_numbers_iter(PacketNumberSpace::ApplicationData).step_by(2);
let pn_a = packet_numbers.next().unwrap();
assert!(ack_ranges.insert_packet_number(pn_a).is_ok());
let pn_b = packet_numbers.next().unwrap();
assert!(ack_ranges.insert_packet_number(pn_b).is_ok());
let pn_c = packet_numbers.next().unwrap();
assert!(ack_ranges.insert_packet_number(pn_c).is_ok());
assert_eq!(ack_ranges.interval_len(), 3);
assert!(ack_ranges.contains(&pn_a));
assert!(ack_ranges.contains(&pn_b));
assert!(ack_ranges.contains(&pn_c));
let pn_d = packet_numbers.next().unwrap();
assert_eq!(
ack_ranges.insert_packet_number(pn_d).err().unwrap(),
Error::LowestRangeDropped {
min: pn_a,
max: pn_a
}
);
assert_eq!(ack_ranges.interval_len(), 3);
assert!(!ack_ranges.contains(&pn_a));
assert!(ack_ranges.contains(&pn_b));
assert!(ack_ranges.contains(&pn_c));
assert!(ack_ranges.contains(&pn_d));
assert_eq!(
ack_ranges.insert_packet_number(pn_a).err().unwrap(),
Error::RangeInsertionFailed {
min: pn_a,
max: pn_a
}
);
assert_eq!(ack_ranges.interval_len(), 3);
assert!(!ack_ranges.contains(&pn_a));
assert!(ack_ranges.contains(&pn_b));
assert!(ack_ranges.contains(&pn_c));
assert!(ack_ranges.contains(&pn_d));
}
#[test]
fn overlapping_range_test() {
let mut packet_numbers = packet_numbers_iter(PacketNumberSpace::ApplicationData).step_by(2); let mut ack_ranges = Ranges::new(3);
let pn_a = packet_numbers.next().unwrap();
let pn_b = packet_numbers.next().unwrap();
let pn_c = packet_numbers.next().unwrap();
let pn_d = packet_numbers.next().unwrap();
let pn_e = packet_numbers.next().unwrap();
let pn_f = packet_numbers.next().unwrap();
let pn_g = packet_numbers.next().unwrap();
let pn_h = packet_numbers.next().unwrap();
let pn_i = packet_numbers.next().unwrap();
let range_0 = PacketNumberRange::new(pn_a, pn_a);
let range_1 = PacketNumberRange::new(pn_b, pn_c);
let range_2 = PacketNumberRange::new(pn_d, pn_f);
let range_3 = PacketNumberRange::new(pn_g, pn_h);
let range_4 = PacketNumberRange::new(pn_h, pn_i);
let range_0_1 = PacketNumberRange::new(pn_a, pn_c);
let range_1_2 = PacketNumberRange::new(pn_c, pn_e);
assert!(ack_ranges.insert_packet_number_range(range_1).is_ok());
assert!(ack_ranges.insert_packet_number_range(range_2).is_ok());
assert!(ack_ranges.insert_packet_number_range(range_3).is_ok());
assert_eq!(ack_ranges.interval_len(), 3);
for pn in range_1 {
assert!(ack_ranges.contains(&pn));
}
for pn in range_2 {
assert!(ack_ranges.contains(&pn));
}
for pn in range_3 {
assert!(ack_ranges.contains(&pn));
}
assert!(ack_ranges.insert_packet_number_range(range_1_2).is_ok());
assert_eq!(ack_ranges.interval_len(), 2);
assert!(ack_ranges.insert_packet_number_range(range_0).is_ok());
assert_eq!(ack_ranges.interval_len(), 3);
assert!(ack_ranges.insert_packet_number_range(range_0_1).is_ok());
assert_eq!(ack_ranges.interval_len(), 2);
assert!(ack_ranges.insert_packet_number_range(range_4).is_ok());
assert_eq!(ack_ranges.interval_len(), 2);
}
#[test]
fn large_range_test() {
let pn_a = PacketNumberSpace::ApplicationData.new_packet_number(VarInt::from_u32(1));
let pn_b = PacketNumberSpace::ApplicationData
.new_packet_number(VarInt::new(varint::MAX_VARINT_VALUE).unwrap());
let mut ack_ranges = Ranges::new(3);
let range_1 = PacketNumberRange::new(pn_a, pn_b);
assert!(ack_ranges.insert_packet_number_range(range_1).is_ok());
assert_eq!(ack_ranges.interval_len(), 1);
}
#[test]
#[cfg_attr(miri, ignore)]
#[cfg(target_pointer_width = "64")]
fn size_of_snapshots() {
use core::mem::size_of;
use insta::assert_debug_snapshot;
assert_debug_snapshot!("Ranges", size_of::<Ranges>());
}
#[test]
fn insert_packet_number_range_fuzz() {
check!()
.with_type::<(u32, u32)>()
.map(|(a, b)| (a.min(b), a.max(b))) .for_each(|(a, b)| {
let mut ack_ranges = Ranges::new(1);
let pn_a = PacketNumberSpace::Initial.new_packet_number(VarInt::from_u32(*a));
let pn_b = PacketNumberSpace::Initial.new_packet_number(VarInt::from_u32(*b));
let range_1 = PacketNumberRange::new(pn_a, pn_b);
assert!(ack_ranges.insert_packet_number_range(range_1).is_ok());
});
}
}