prns_runtime/manifold/
grant.rs1use crate::engine::FanTarget;
2use crate::interfaces::{FrameSink, FrameSinkError, InterfaceId, PacketPhyStats, INTERFACE_ID_LEN};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[repr(C)]
7pub enum FrameTarget {
8 Direct(InterfaceId),
9 Fan(FanTarget),
10}
11
12pub struct FrameSlot<const FRAME: usize> {
13 pub target: FrameTarget,
14 pub len: usize,
15 pub bytes: [u8; FRAME],
16 pub packet_phy: PacketPhyStats,
17}
18
19impl<const FRAME: usize> FrameSlot<FRAME> {
20 pub const fn empty() -> Self {
21 Self {
22 target: FrameTarget::Direct(InterfaceId::new([0u8; INTERFACE_ID_LEN])),
23 len: 0,
24 bytes: [0u8; FRAME],
25 packet_phy: PacketPhyStats {
26 rssi: None,
27 snr: None,
28 quality: None,
29 },
30 }
31 }
32
33 fn fill(&mut self, frame: &[u8]) {
34 self.packet_phy = PacketPhyStats::default();
35 debug_assert!(
36 frame.len() <= FRAME,
37 "a {}-byte frame cannot fit this {FRAME}-byte slot",
38 frame.len()
39 );
40 let len = frame.len().min(FRAME);
41 self.bytes[..len].copy_from_slice(&frame[..len]);
42 self.len = len;
43 }
44
45 pub fn fill_for(&mut self, interface_id: InterfaceId, frame: &[u8]) {
46 self.target = FrameTarget::Direct(interface_id);
47 self.fill(frame);
48 }
49
50 pub fn fill_for_fan(&mut self, fan: FanTarget, frame: &[u8]) {
51 self.target = FrameTarget::Fan(fan);
52 self.fill(frame);
53 }
54
55 pub fn frame(&self) -> &[u8] {
56 &self.bytes[..self.len]
57 }
58
59 pub fn frame_mut(&mut self) -> &mut [u8] {
60 let len = self.len;
61 &mut self.bytes[..len]
62 }
63}
64
65impl<const FRAME: usize> FrameSink for FrameSlot<FRAME> {
67 fn clear(&mut self) {
68 self.len = 0;
69 self.packet_phy = PacketPhyStats::default();
70 }
71
72 fn frame_len(&self) -> usize {
73 self.len
74 }
75
76 fn free_capacity(&self) -> usize {
77 FRAME.saturating_sub(self.len)
78 }
79
80 fn push(&mut self, byte: u8) -> Result<(), FrameSinkError> {
81 if self.len >= FRAME {
82 return Err(FrameSinkError::Full);
83 }
84 self.bytes[self.len] = byte;
85 self.len += 1;
86 Ok(())
87 }
88
89 fn extend_from_slice(&mut self, run: &[u8]) -> Result<(), FrameSinkError> {
90 if run.len() > FRAME.saturating_sub(self.len) {
91 return Err(FrameSinkError::Full);
92 }
93 self.bytes[self.len..self.len + run.len()].copy_from_slice(run);
94 self.len += run.len();
95 Ok(())
96 }
97}
98
99#[allow(async_fn_in_trait)]
100pub trait GrantProducer<const FRAME: usize> {
101 fn try_grant(&mut self) -> Option<&mut FrameSlot<FRAME>>;
102 async fn grant(&mut self) -> &mut FrameSlot<FRAME>;
103 fn commit(&mut self);
104}
105
106#[allow(async_fn_in_trait)]
107pub trait GrantConsumer<const FRAME: usize> {
108 fn try_peek(&mut self) -> Option<&mut FrameSlot<FRAME>>;
109 async fn peek(&mut self) -> &mut FrameSlot<FRAME>;
110 fn release(&mut self);
111}
112
113pub trait ManifoldLaneReader: Send {
114 fn try_read(&mut self) -> Option<(FrameTarget, PacketPhyStats, &mut [u8])>;
115 fn release(&mut self);
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, Eq)]
119#[must_use]
120pub enum LaneWriteOutcome {
121 Written,
122 Full,
123 FrameTooLarge { frame_len: usize, capacity: usize },
124}
125
126pub trait ManifoldLaneWriter: Send {
127 fn try_write(&mut self, target: FrameTarget, frame: &[u8]) -> LaneWriteOutcome;
128}