1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Wire data format helper functions

use crate::frame_pool::FrameBox;
use postcard_rpc::{Endpoint, Topic, WireHeader};
use serde::Serialize;

/// A borrowed view of a frame that contains a postcard-rpc message.
pub struct WhBody<'a> {
    /// The postcard-rpc Wire Header
    pub wh: WireHeader,
    /// The body of the frame
    pub body: &'a [u8],
}

impl<'a> WhBody<'a> {
    /// Attempt to decode a [postcard-rpc] frame from a FrameBox
    pub fn try_from(fb: &'a FrameBox) -> Option<Self> {
        let (_a, remain) = fb.split_first()?;
        let (wh, body) = postcard_rpc::headered::extract_header_from_bytes(remain).ok()?;
        Some(WhBody { wh, body })
    }
}

#[inline]
fn build_reply_keyed<T: Serialize>(
    mut buf: FrameBox,
    wh: &WireHeader,
    msg: &T,
) -> Option<FrameBox> {
    if buf.is_empty() {
        return None;
    }
    // Split off the address, but DON'T write it!
    //
    // "userspace" doesn't actually know our wire addr, it gets
    // added at send time.
    let (_a, remain) = buf.split_first_mut()?;
    // Then add the wireheader
    let used1 = postcard::to_slice(wh, remain).ok()?.len();
    let (_hdr, remain) = remain.split_at_mut(used1);
    // Then add the body
    let used2 = postcard::to_slice(msg, remain).ok()?.len();

    // TODO: Add CRC?

    let ttl_len = 1 + used1 + used2;
    buf.set_len(ttl_len);

    Some(buf)
}

/// Prepare a `Topic` message for sending
pub fn send_topic<T>(buf: FrameBox, seq_no: u32, msg: &T::Message) -> Option<FrameBox>
where
    T: Topic,
    T::Message: Serialize,
{
    let wh = WireHeader {
        key: T::TOPIC_KEY,
        seq_no,
    };
    build_reply_keyed::<T::Message>(buf, &wh, msg)
}

/// Prepare an `Endpoint` `Response` message for sending
pub fn reply_endpoint<E>(buf: FrameBox, seq_no: u32, msg: &E::Response) -> Option<FrameBox>
where
    E: Endpoint,
    E::Response: Serialize,
{
    let wh = WireHeader {
        key: E::RESP_KEY,
        seq_no,
    };
    build_reply_keyed::<E::Response>(buf, &wh, msg)
}