use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::channel::Sender;
use crate::interfaces::{FrameSink, InterfaceId, PacketPhyStats};
use crate::manifold::grant::{FrameTarget, GrantConsumer, GrantProducer};
use crate::manifold::interface_seam::{InterfaceSeam, OutboundDisposition};
use super::{EmbassyGrantConsumer, EmbassyGrantProducer};
pub struct EmbassyInterfaceSeam<'a, M: RawMutex, const NOTIFY: usize, const FRAME: usize> {
id: InterfaceId,
inbound: EmbassyGrantProducer<'a, M, FRAME>,
notify: Sender<'a, M, InterfaceId, NOTIFY>,
outbound: EmbassyGrantConsumer<'a, M, FRAME>,
fill_entropy: fn(&mut [u8]),
}
impl<'a, M: RawMutex, const NOTIFY: usize, const FRAME: usize>
EmbassyInterfaceSeam<'a, M, NOTIFY, FRAME>
{
#[must_use]
pub fn new(
id: InterfaceId,
inbound: EmbassyGrantProducer<'a, M, FRAME>,
notify: Sender<'a, M, InterfaceId, NOTIFY>,
outbound: EmbassyGrantConsumer<'a, M, FRAME>,
fill_entropy: fn(&mut [u8]),
) -> Self {
Self {
id,
inbound,
notify,
outbound,
fill_entropy,
}
}
}
impl<M: RawMutex, const NOTIFY: usize, const FRAME: usize> InterfaceSeam
for EmbassyInterfaceSeam<'_, M, NOTIFY, FRAME>
{
fn fill_entropy(&mut self, bytes: &mut [u8]) {
(self.fill_entropy)(bytes);
}
async fn inbound_sink(&mut self) -> &mut dyn FrameSink {
let slot = self.inbound.grant().await;
slot.target = FrameTarget::Direct(self.id);
slot
}
async fn commit_inbound(&mut self) {
let slot = self.inbound.grant().await;
if slot.len == 0 {
return;
}
self.inbound.commit();
let _ = self.notify.try_send(self.id);
}
async fn next_inbound_with_phy(&mut self, frame: &[u8], packet_phy: PacketPhyStats) {
let slot = self.inbound.grant().await;
slot.clear();
if slot.extend_from_slice(frame).is_err() {
return;
}
slot.packet_phy = packet_phy;
self.commit_inbound().await;
}
async fn next_outbound(&mut self) -> &[u8] {
self.outbound.release();
self.outbound.peek().await.frame()
}
fn accept_outbound_custody(&mut self) {
self.outbound.release();
}
fn complete_outbound(&mut self, _disposition: OutboundDisposition) {
self.outbound.release();
}
}
#[cfg(test)]
mod tests;