ergot_base/interface_manager/utils/
framed_stream.rs

1//! Framed Stream
2//!
3//! The "Framed Stream" is one flavor of interface sinks. It is intended for packet-like
4//! interfaces that do NOT require framing in software.
5
6use bbq2::{prod_cons::framed::FramedProducer, traits::bbqhdl::BbqHandle};
7use postcard::ser_flavors;
8use serde::Serialize;
9
10use crate::{
11    AnyAllAppendix, FrameKind, ProtocolError,
12    interface_manager::InterfaceSink,
13    wire_frames::{self, CommonHeader},
14};
15
16pub struct Sink<Q>
17where
18    Q: BbqHandle,
19{
20    pub(crate) mtu: u16,
21    pub(crate) prod: FramedProducer<Q, u16>,
22}
23
24#[allow(clippy::result_unit_err)] // todo
25impl<Q> Sink<Q>
26where
27    Q: BbqHandle,
28{
29    pub fn new_from_handle(q: Q, mtu: u16) -> Self {
30        Self {
31            mtu,
32            prod: q.framed_producer(),
33        }
34    }
35
36    pub const fn new(prod: FramedProducer<Q, u16>, mtu: u16) -> Self {
37        Self { mtu, prod }
38    }
39}
40
41impl<Q> InterfaceSink for Sink<Q>
42where
43    Q: BbqHandle,
44{
45    fn send_ty<T: Serialize>(
46        &mut self,
47        hdr: &CommonHeader,
48        apdx: Option<&AnyAllAppendix>,
49        body: &T,
50    ) -> Result<(), ()> {
51        let is_err = hdr.kind == FrameKind::PROTOCOL_ERROR;
52
53        if is_err {
54            // todo: use a different interface for this
55            return Err(());
56        }
57        let mut wgr = self.prod.grant(self.mtu).map_err(drop)?;
58
59        let ser = ser_flavors::Slice::new(&mut wgr);
60        let used = wire_frames::encode_frame_ty(ser, hdr, apdx, body).map_err(drop)?;
61        let len = used.len() as u16;
62        wgr.commit(len);
63
64        Ok(())
65    }
66
67    fn send_raw(&mut self, hdr: &CommonHeader, hdr_raw: &[u8], body: &[u8]) -> Result<(), ()> {
68        let is_err = hdr.kind == FrameKind::PROTOCOL_ERROR;
69
70        if is_err {
71            // todo: use a different interface for this
72            return Err(());
73        }
74        let len = hdr_raw.len() + body.len();
75        let Ok(len) = u16::try_from(len) else {
76            return Err(());
77        };
78        let mut wgr = self.prod.grant(len).map_err(drop)?;
79        let (ghdr, gbody) = wgr.split_at_mut(hdr_raw.len());
80        ghdr.copy_from_slice(hdr_raw);
81        gbody.copy_from_slice(body);
82
83        wgr.commit(len);
84
85        Ok(())
86    }
87
88    fn send_err(&mut self, hdr: &CommonHeader, err: ProtocolError) -> Result<(), ()> {
89        let is_err = hdr.kind == FrameKind::PROTOCOL_ERROR;
90
91        // note: here it SHOULD be an err!
92        if !is_err {
93            // todo: use a different interface for this
94            return Err(());
95        }
96        let mut wgr = self.prod.grant(self.mtu).map_err(drop)?;
97
98        let ser = ser_flavors::Slice::new(&mut wgr);
99        let used = wire_frames::encode_frame_err(ser, hdr, err).map_err(drop)?;
100        let len = used.len() as u16;
101        wgr.commit(len);
102
103        Ok(())
104    }
105}