simple_message_channels/
message.rs

1use crate::MAX_MESSAGE_SIZE;
2use async_std::io::{Error, ErrorKind};
3
4/// A SMC message.
5#[derive(Debug)]
6pub struct Message {
7    pub channel: u64,
8    pub typ: u8,
9    pub message: Vec<u8>,
10}
11
12impl Message {
13    /// Create a new message.
14    pub fn new(channel: u64, typ: u8, message: Vec<u8>) -> Message {
15        Message {
16            channel,
17            typ,
18            message,
19        }
20    }
21
22    /// Decode a message from `buf` (bytes).
23    ///
24    /// Note: `buf` has to have a valid length, and the length
25    /// prefix has to be removed already.
26    pub fn from_buf(buf: &[u8]) -> Result<Message, Error> {
27        decode_message(buf)
28    }
29
30    /// Encode a message body into a buffer.
31    ///
32    /// The result can be sent directly over any medium.
33    /// It is length-prefixed, so chunking should not be an issue.
34    pub fn encode(&self) -> Result<Vec<u8>, Error> {
35        encode_message(self)
36    }
37}
38
39/// Decode a message from `buf` (bytes).
40///
41/// Note: `buf` has to have a valid length, and the length prefixed
42/// has to be removed already.
43pub fn decode_message(buf: &[u8]) -> Result<Message, Error> {
44    if buf.len() == 0 {
45        return Err(Error::new(
46            ErrorKind::UnexpectedEof,
47            "received empty message",
48        ));
49    }
50    let mut header = 0 as u64;
51    let headerlen = varinteger::decode(buf, &mut header);
52    let msg = &buf[headerlen..];
53    let channel = header >> 4;
54    let typ = header & 0b1111;
55    let message = Message {
56        channel: channel,
57        typ: typ as u8,
58        message: msg.to_vec(),
59    };
60    Ok(message)
61}
62
63/// Encode a message body into a buffer.
64pub fn encode_message(msg: &Message) -> Result<Vec<u8>, Error> {
65    let header = msg.channel << 4 | msg.typ as u64;
66    let len_header = varinteger::length(header);
67    let len_body = msg.message.len() + len_header;
68    let len_prefix = varinteger::length(len_body as u64);
69    let len = len_body + len_prefix;
70
71    if len as u64 > MAX_MESSAGE_SIZE {
72        return Err(Error::new(ErrorKind::InvalidInput, "Message too long"));
73    }
74
75    let mut buf = vec![0; len];
76
77    varinteger::encode(len_body as u64, &mut buf[..len_prefix]);
78    let end = len_prefix + len_header;
79    varinteger::encode(header, &mut buf[len_prefix..end]);
80    &mut buf[end..].copy_from_slice(&msg.message);
81    Ok(buf)
82}