#![allow(dead_code)]
use alloc::vec::Vec;
use core::ops::RangeInclusive;
use core::time::Duration;
use crate::quic::pn::AckRanges;
use crate::quic::varint;
use crate::tls::Error;
pub(crate) fn build_ack_payload(
ranges: &AckRanges,
largest_arrival: Duration,
now: Duration,
ack_delay_exponent: u8,
) -> Vec<u8> {
let stored = ranges.ranges();
let mut out = Vec::new();
if stored.is_empty() {
return out;
}
let largest = *stored[0].end();
let first_range = largest - *stored[0].start();
let delta_us = now.saturating_sub(largest_arrival).as_micros() as u64;
let scaled = delta_us >> (ack_delay_exponent as u32).min(62);
varint::encode(largest, &mut out);
varint::encode(scaled, &mut out);
let mut trailing = Vec::new();
let mut count = 0u64;
for i in 1..stored.len() {
let prev_smallest = *stored[i - 1].start();
let cur_largest = *stored[i].end();
let cur_smallest = *stored[i].start();
let gap_wire = prev_smallest
.checked_sub(cur_largest)
.and_then(|v| v.checked_sub(2));
let gap_wire = match gap_wire {
Some(v) => v,
None => continue, };
let len_wire = cur_largest - cur_smallest;
varint::encode(gap_wire, &mut trailing);
varint::encode(len_wire, &mut trailing);
count += 1;
}
varint::encode(count, &mut out);
varint::encode(first_range, &mut out);
out.extend_from_slice(&trailing);
out
}
pub(crate) fn build_ack_frame(
ranges: &AckRanges,
largest_arrival: Duration,
now: Duration,
ack_delay_exponent: u8,
) -> Vec<u8> {
let mut out = Vec::new();
if ranges.is_empty() {
return out;
}
out.push(0x02);
let payload = build_ack_payload(ranges, largest_arrival, now, ack_delay_exponent);
out.extend_from_slice(&payload);
out
}
pub(crate) fn parse_ack_payload(body: &[u8]) -> Result<(Vec<RangeInclusive<u64>>, u64), Error> {
let mut p = 0usize;
let (largest, n) = varint::decode(&body[p..])?;
p += n;
let (ack_delay_raw, n) = varint::decode(&body[p..])?;
p += n;
let (range_count, n) = varint::decode(&body[p..])?;
p += n;
let (first_range, n) = varint::decode(&body[p..])?;
p += n;
if first_range > largest {
return Err(Error::Decode);
}
let capacity_hint = core::cmp::min(range_count as usize, body.len() / 2);
let mut ranges: Vec<RangeInclusive<u64>> = Vec::with_capacity(1 + capacity_hint);
let mut smallest_in_block = largest - first_range;
ranges.push(smallest_in_block..=largest);
for _ in 0..range_count {
let (gap_wire, n) = varint::decode(&body[p..])?;
p += n;
let (len_wire, n) = varint::decode(&body[p..])?;
p += n;
let sub = gap_wire.checked_add(2).ok_or(Error::Decode)?;
if smallest_in_block < sub {
return Err(Error::Decode);
}
let cur_largest = smallest_in_block - sub;
if len_wire > cur_largest {
return Err(Error::Decode);
}
let cur_smallest = cur_largest - len_wire;
ranges.push(cur_smallest..=cur_largest);
smallest_in_block = cur_smallest;
}
Ok((ranges, ack_delay_raw))
}
#[cfg(test)]
mod tests {
use super::*;
fn ranges_from(pns: &[u64]) -> AckRanges {
let mut r = AckRanges::new();
for &p in pns {
r.insert(p);
}
r
}
#[test]
fn ack_frame_roundtrip_boundary_cases() {
let cases: &[&[u64]] = &[
&[5], &[5, 6], &[5, 9], &[1, 2, 5, 6], &[0], &[0, 1, 2, 5, 6, 10, 20],
];
for pns in cases {
let r = ranges_from(pns);
let payload = build_ack_payload(&r, Duration::ZERO, Duration::ZERO, 3);
let (decoded, ack_delay) = parse_ack_payload(&payload).expect("parse");
assert_eq!(ack_delay, 0, "ack_delay zero for now==arrival");
let stored = r.ranges();
assert_eq!(decoded.len(), stored.len(), "case {pns:?}: range count");
for (got, want) in decoded.iter().zip(stored.iter()) {
assert_eq!(got, want, "case {pns:?}");
}
}
}
#[test]
fn ack_frame_boundary_wire_bytes() {
let p = build_ack_payload(&ranges_from(&[5]), Duration::ZERO, Duration::ZERO, 3);
assert_eq!(p, alloc::vec![0x05, 0x00, 0x00, 0x00], "{{one PN=5}}");
let p = build_ack_payload(&ranges_from(&[5, 6]), Duration::ZERO, Duration::ZERO, 3);
assert_eq!(p, alloc::vec![0x06, 0x00, 0x00, 0x01], "{{two PNs}}");
let p = build_ack_payload(&ranges_from(&[5, 9]), Duration::ZERO, Duration::ZERO, 3);
assert_eq!(
p,
alloc::vec![0x09, 0x00, 0x01, 0x00, 0x02, 0x00],
"{{two single disjoint PNs}}"
);
let p = build_ack_payload(
&ranges_from(&[1, 2, 5, 6]),
Duration::ZERO,
Duration::ZERO,
3,
);
assert_eq!(
p,
alloc::vec![0x06, 0x00, 0x01, 0x01, 0x01, 0x01],
"{{two pairs of two}}"
);
let p = build_ack_payload(&ranges_from(&[0]), Duration::ZERO, Duration::ZERO, 3);
assert_eq!(p, alloc::vec![0x00, 0x00, 0x00, 0x00], "{{one PN at 0}}");
}
#[test]
fn full_frame_starts_with_0x02() {
let r = ranges_from(&[5]);
let frame = build_ack_frame(&r, Duration::ZERO, Duration::ZERO, 3);
assert!(!frame.is_empty());
assert_eq!(frame[0], 0x02);
}
#[test]
fn ack_delay_scales_by_exponent() {
let r = ranges_from(&[5]);
let now = Duration::from_micros(800);
let arrival = Duration::from_micros(0);
let payload = build_ack_payload(&r, arrival, now, 3);
let (_, ack_delay) = parse_ack_payload(&payload).expect("parse");
assert_eq!(ack_delay, 100);
let payload = build_ack_payload(&r, arrival, now, 10);
let (_, ack_delay) = parse_ack_payload(&payload).expect("parse");
assert_eq!(ack_delay, 0);
}
#[test]
fn empty_ranges_emits_empty() {
let r = AckRanges::new();
assert!(build_ack_payload(&r, Duration::ZERO, Duration::ZERO, 3).is_empty());
assert!(build_ack_frame(&r, Duration::ZERO, Duration::ZERO, 3).is_empty());
}
#[test]
fn two_pairs_of_two_value_minus_one_encoding() {
let r = ranges_from(&[1, 2, 5, 6]);
let payload = build_ack_payload(&r, Duration::ZERO, Duration::ZERO, 3);
let mut p = 0;
let (largest, n) = varint::decode(&payload[p..]).unwrap();
p += n;
assert_eq!(largest, 6);
let (_ack_delay, n) = varint::decode(&payload[p..]).unwrap();
p += n;
let (range_count, n) = varint::decode(&payload[p..]).unwrap();
p += n;
assert_eq!(range_count, 1);
let (first_range, n) = varint::decode(&payload[p..]).unwrap();
p += n;
assert_eq!(first_range, 1);
let (gap_wire, n) = varint::decode(&payload[p..]).unwrap();
p += n;
assert_eq!(gap_wire, 1, "gap_wire = real_gap(2) − 1 = 1");
let (len_wire, _) = varint::decode(&payload[p..]).unwrap();
assert_eq!(len_wire, 1, "len_wire = (real_len=2) − 1 = 1");
}
#[test]
fn ack_delay_exponent_3_for_initial_handshake() {
let r = ranges_from(&[5]);
let arrival = Duration::from_micros(0);
let now = Duration::from_micros(128);
let payload = build_ack_payload(&r, arrival, now, 3);
let (_ranges, ack_delay_raw) = parse_ack_payload(&payload).expect("parse");
let reconstructed = Duration::from_micros(ack_delay_raw << 3);
assert_eq!(reconstructed, now - arrival);
}
#[test]
fn pn_at_zero_roundtrips() {
let r = ranges_from(&[0]);
let payload = build_ack_payload(&r, Duration::ZERO, Duration::ZERO, 3);
let (decoded, _) = parse_ack_payload(&payload).expect("parse");
assert_eq!(decoded, alloc::vec![0u64..=0u64]);
}
}