ergot_base/interface_manager/
framed_stream.rs

1use bbq2::{prod_cons::framed::FramedProducer, traits::bbqhdl::BbqHandle};
2use postcard::ser_flavors;
3use serde::Serialize;
4
5use crate::{
6    AnyAllAppendix, FrameKind, ProtocolError,
7    wire_frames::{self, CommonHeader},
8};
9
10pub struct Interface<Q>
11where
12    Q: BbqHandle,
13{
14    pub(crate) mtu: u16,
15    pub(crate) prod: FramedProducer<Q, u16>,
16}
17
18#[allow(clippy::result_unit_err)] // todo
19impl<Q> Interface<Q>
20where
21    Q: BbqHandle,
22{
23    pub fn send_ty<T: Serialize>(
24        &mut self,
25        hdr: &CommonHeader,
26        apdx: Option<&AnyAllAppendix>,
27        body: &T,
28    ) -> Result<(), ()> {
29        let is_err = hdr.kind == FrameKind::PROTOCOL_ERROR;
30
31        if is_err {
32            // todo: use a different interface for this
33            return Err(());
34        }
35        let mut wgr = self.prod.grant(self.mtu).map_err(drop)?;
36
37        let ser = ser_flavors::Slice::new(&mut wgr);
38        let used = wire_frames::encode_frame_ty(ser, hdr, apdx, body).map_err(drop)?;
39        let len = used.len() as u16;
40        wgr.commit(len);
41
42        Ok(())
43    }
44
45    pub fn send_raw(&mut self, hdr: &CommonHeader, hdr_raw: &[u8], body: &[u8]) -> Result<(), ()> {
46        let is_err = hdr.kind == FrameKind::PROTOCOL_ERROR;
47
48        if is_err {
49            // todo: use a different interface for this
50            return Err(());
51        }
52        let len = hdr_raw.len() + body.len();
53        let Ok(len) = u16::try_from(len) else {
54            return Err(());
55        };
56        let mut wgr = self.prod.grant(len).map_err(drop)?;
57        let (ghdr, gbody) = wgr.split_at_mut(hdr_raw.len());
58        ghdr.copy_from_slice(hdr_raw);
59        gbody.copy_from_slice(body);
60
61        wgr.commit(len);
62
63        Ok(())
64    }
65
66    pub fn send_err(&mut self, hdr: &CommonHeader, err: ProtocolError) -> Result<(), ()> {
67        let is_err = hdr.kind == FrameKind::PROTOCOL_ERROR;
68
69        // note: here it SHOULD be an err!
70        if !is_err {
71            // todo: use a different interface for this
72            return Err(());
73        }
74        let mut wgr = self.prod.grant(self.mtu).map_err(drop)?;
75
76        let ser = ser_flavors::Slice::new(&mut wgr);
77        let used = wire_frames::encode_frame_err(ser, hdr, err).map_err(drop)?;
78        let len = used.len() as u16;
79        wgr.commit(len);
80
81        Ok(())
82    }
83}