rns_embedded_core/
replay.rs1#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2pub struct ReplayWindow {
3 highest: Option<u64>,
4 seen: u64,
5}
6
7impl ReplayWindow {
8 pub fn new() -> Self {
9 Self { highest: None, seen: 0 }
10 }
11
12 pub fn highest(&self) -> Option<u64> {
13 self.highest
14 }
15
16 pub fn accept(&mut self, sequence: u64) -> bool {
17 match self.highest {
18 None => {
19 self.highest = Some(sequence);
20 self.seen = 1;
21 true
22 }
23 Some(highest) if sequence > highest => {
24 let shift = sequence.saturating_sub(highest);
25 self.seen = if shift >= 64 { 0 } else { self.seen << (shift as u32) };
26 self.highest = Some(sequence);
27 self.seen |= 1;
28 true
29 }
30 Some(highest) => {
31 let delta = highest - sequence;
32 if delta >= 64 {
33 return false;
34 }
35 let bit = 1_u64 << (delta as u32);
36 if (self.seen & bit) != 0 {
37 return false;
38 }
39 self.seen |= bit;
40 true
41 }
42 }
43 }
44}
45
46impl Default for ReplayWindow {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::ReplayWindow;
55
56 #[test]
57 fn accepts_forward_and_rejects_duplicates() {
58 let mut window = ReplayWindow::new();
59 assert!(window.accept(10));
60 assert!(window.accept(11));
61 assert!(!window.accept(11));
62 assert!(window.accept(9));
63 assert!(!window.accept(9));
64 }
65
66 #[test]
67 fn rejects_far_old_sequences() {
68 let mut window = ReplayWindow::new();
69 assert!(window.accept(200));
70 assert!(!window.accept(100));
71 }
72}