use crate::frame;
use crate::MAX_FRAGMENT_SIZE;
use std::cell::RefCell;
use std::rc::Rc;
use std::rc::Weak;
#[derive(Debug)]
pub struct PendingPacket {
data: Box<[u8]>,
channel_id: u8,
sequence_id: u32,
window_parent_lead: u16,
channel_parent_lead: u16,
last_fragment_id: u16,
ack_flags: Box<[u64]>,
}
impl PendingPacket {
pub fn new(data: Box<[u8]>, channel_id: u8,
sequence_id: u32, window_parent_lead: u16, channel_parent_lead: u16) -> Self {
let num_fragments = (data.len() + MAX_FRAGMENT_SIZE - 1) / MAX_FRAGMENT_SIZE + (data.len() == 0) as usize;
debug_assert!(num_fragments != 0);
debug_assert!(num_fragments - 1 <= u16::MAX as usize);
let last_fragment_id = (num_fragments - 1) as u16;
Self {
data,
channel_id,
sequence_id,
window_parent_lead,
channel_parent_lead,
last_fragment_id,
ack_flags: vec![0u64; (num_fragments + 63)/64].into_boxed_slice(),
}
}
#[cfg(test)]
pub fn sequence_id(&self) -> u32 {
self.sequence_id
}
#[cfg(test)]
pub fn channel_id(&self) -> u8 {
self.channel_id
}
#[cfg(test)]
pub fn window_parent_lead(&self) -> u16 {
self.window_parent_lead
}
#[cfg(test)]
pub fn channel_parent_lead(&self) -> u16 {
self.channel_parent_lead
}
pub fn last_fragment_id(&self) -> u16 {
self.last_fragment_id
}
pub fn fragment_acknowledged(&self, fragment_id: u16) -> bool {
let flag_bit = 1 << (fragment_id % 64) as u64;
let flags_index = (fragment_id / 64) as usize;
self.ack_flags[flags_index] & flag_bit != 0
}
pub fn acknowledge_fragment(&mut self, fragment_id: u16) {
let flag_bit = 1 << (fragment_id % 64) as u64;
let flags_index = (fragment_id / 64) as usize;
self.ack_flags[flags_index] |= flag_bit;
}
pub fn size(&self) -> usize {
self.data.len()
}
pub fn datagram<'a>(&'a self, fragment_id: u16) -> frame::DatagramRef<'a> {
debug_assert!(fragment_id <= self.last_fragment_id);
let i = fragment_id as usize;
let data = if fragment_id == self.last_fragment_id {
&self.data[i * MAX_FRAGMENT_SIZE .. ]
} else {
&self.data[i * MAX_FRAGMENT_SIZE .. (i + 1)*MAX_FRAGMENT_SIZE]
};
frame::DatagramRef {
sequence_id: self.sequence_id,
channel_id: self.channel_id,
window_parent_lead: self.window_parent_lead,
channel_parent_lead: self.channel_parent_lead,
fragment_id,
fragment_id_last: self.last_fragment_id,
data,
}
}
}
pub type PendingPacketRc = Rc<RefCell<PendingPacket>>;
pub type PendingPacketWeak = Weak<RefCell<PendingPacket>>;
#[derive(Debug)]
pub struct FragmentRef {
pub packet: PendingPacketWeak,
pub fragment_id: u16,
}
impl Clone for FragmentRef {
fn clone(&self) -> Self {
Self {
packet: Weak::clone(&self.packet),
fragment_id: self.fragment_id,
}
}
}
impl FragmentRef {
pub fn new(packet_rc: &PendingPacketRc, fragment_id: u16) -> Self {
Self {
packet: Rc::downgrade(packet_rc),
fragment_id,
}
}
}