librqbit_utp/raw/
selective_ack.rs1use bitvec::{BitArr, order::Lsb0, slice::BitSlice};
2
3use crate::constants::SACK_DEPTH;
4
5type SelectiveAckData = BitArr!(for SACK_DEPTH, in u8, Lsb0);
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct SelectiveAck {
9 data: SelectiveAckData,
10 len: usize,
11}
12
13impl SelectiveAck {
14 pub fn new(unacked: impl Iterator<Item = usize>) -> Self {
15 let mut data = SelectiveAckData::default();
16 for idx in unacked.take_while(|i| *i < SACK_DEPTH) {
17 data.set(idx, true);
18 }
19 Self {
20 data,
21 len: SACK_DEPTH,
22 }
23 }
24
25 #[cfg(test)]
26 pub fn new_test(acked: impl IntoIterator<Item = usize>) -> Option<Self> {
27 let mut data = SelectiveAckData::default();
28 let mut count = 0;
29 for idx in acked {
30 data.get_mut(idx).unwrap().set(true);
31 count += 1;
32 }
33 if count > 0 {
34 Some(Self {
35 data,
36 len: SACK_DEPTH,
37 })
38 } else {
39 None
40 }
41 }
42
43 #[allow(clippy::len_without_is_empty)]
44 pub fn len(&self) -> usize {
45 self.len
46 }
47
48 pub fn as_bytes(&self) -> &[u8] {
49 self.data.as_raw_slice()
50 }
51
52 pub fn deserialize(bytes: &[u8]) -> Self {
53 let len = bytes.len().min(std::mem::size_of::<SelectiveAckData>());
60 let mut data = SelectiveAckData::default();
61 data.as_raw_mut_slice()[..len].copy_from_slice(&bytes[..len]);
62 Self {
63 data,
64 len: bytes.len() * 8,
65 }
66 }
67
68 pub fn as_bitslice(&self) -> &BitSlice<u8> {
69 self.data.as_bitslice()
70 }
71
72 pub fn iter(&self) -> impl Iterator<Item = bool> + '_ {
73 self.data.iter().map(|b| *b)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use std::num::NonZeroUsize;
80
81 use crate::{
82 message::UtpMessage,
83 raw::{Type::ST_DATA, selective_ack::SelectiveAck},
84 stream_rx::OutOfOrderQueue,
85 };
86
87 fn asm() -> OutOfOrderQueue {
88 OutOfOrderQueue::new(NonZeroUsize::new(65).unwrap())
89 }
90
91 fn msg() -> UtpMessage {
92 UtpMessage::new_test(
93 crate::raw::UtpHeader {
94 htype: ST_DATA,
95 ..Default::default()
96 },
97 b"a",
98 )
99 }
100
101 #[test]
102 fn test_empty_is_none() {
103 let asm = asm();
104 assert!(asm.selective_ack().is_none());
105 }
106
107 #[test]
108 fn test_holes() {
109 let mut asm = asm();
110 asm.add_remove(msg(), 8).unwrap();
111 asm.add_remove(msg(), 1).unwrap();
112 asm.add_remove(msg(), 2).unwrap();
113 asm.add_remove(msg(), 64).unwrap();
114
115 let sack = asm.selective_ack().unwrap();
116 assert_eq!(
117 sack.data.as_raw_slice(),
118 [0b1000_0011, 0, 0, 0, 0, 0, 0, 0b1000_0000]
119 );
120
121 assert_eq!(sack, SelectiveAck::deserialize(sack.as_bytes()));
122 }
123}