Skip to main content

prns_runtime/runtime/packet_phy_retention/
heap.rs

1use core::num::NonZeroUsize;
2
3use alloc::vec::Vec;
4use prns_core::lemire_index::HeapLemireIndex;
5
6use crate::interfaces::{RssiDbm, SignalQualityTenthsPercent, SnrQuarterDb};
7use crate::routing::dedup::PacketHash;
8
9use super::{PacketMetricStorage, PacketPhyRetention};
10
11pub const RNS_1_4_2_PACKET_PHY_CAPACITY: usize = 512;
12
13pub struct HeapPacketMetricStorage<Metric, const CAPACITY: usize> {
14    packet_hashes: Vec<PacketHash>,
15    metrics: Vec<Metric>,
16    index: HeapLemireIndex,
17}
18
19impl<Metric, const CAPACITY: usize> Default for HeapPacketMetricStorage<Metric, CAPACITY> {
20    fn default() -> Self {
21        const {
22            assert!(
23                CAPACITY > 0,
24                "packet PHY retention capacity must be non-zero"
25            );
26            assert!(
27                CAPACITY < u32::MAX as usize,
28                "heap packet PHY retention exceeds its index slot range"
29            );
30        }
31        Self {
32            packet_hashes: Vec::with_capacity(CAPACITY),
33            metrics: Vec::with_capacity(CAPACITY),
34            index: HeapLemireIndex::default(),
35        }
36    }
37}
38
39impl<Metric: Copy, const CAPACITY: usize> PacketMetricStorage
40    for HeapPacketMetricStorage<Metric, CAPACITY>
41{
42    type Metric = Metric;
43
44    fn capacity(&self) -> NonZeroUsize {
45        match NonZeroUsize::new(CAPACITY) {
46            Some(capacity) => capacity,
47            None => unreachable!("packet PHY retention capacity is non-zero"),
48        }
49    }
50
51    fn len(&self) -> usize {
52        self.packet_hashes.len()
53    }
54
55    fn append(&mut self, packet_hash: PacketHash, metric: Metric) {
56        self.packet_hashes.push(packet_hash);
57        self.metrics.push(metric);
58        self.index
59            .insert(self.packet_hashes.len() - 1, &self.packet_hashes);
60    }
61
62    fn replace(&mut self, slot: usize, packet_hash: PacketHash, metric: Metric) {
63        self.index.remove_slot(slot, &self.packet_hashes);
64        self.packet_hashes[slot] = packet_hash;
65        self.metrics[slot] = metric;
66        self.index.insert(slot, &self.packet_hashes);
67    }
68
69    fn get(&self, packet_hash: PacketHash) -> Option<Metric> {
70        self.index
71            .get(&packet_hash, &self.packet_hashes)
72            .map(|slot| self.metrics[slot])
73    }
74}
75
76pub type HeapPacketPhyRetention = PacketPhyRetention<
77    HeapPacketMetricStorage<RssiDbm, RNS_1_4_2_PACKET_PHY_CAPACITY>,
78    HeapPacketMetricStorage<SnrQuarterDb, RNS_1_4_2_PACKET_PHY_CAPACITY>,
79    HeapPacketMetricStorage<SignalQualityTenthsPercent, RNS_1_4_2_PACKET_PHY_CAPACITY>,
80>;