Skip to main content

secure_serial/
protocol.rs

1//! Wire format constants and the in-band acknowledgement record.
2//!
3//! Frames begin with [`MAGIC`], followed by a length byte, packet type, and payload; see the crate
4//! README for the full layout. [`CHUNK_LEN_MAX`] is the maximum size of one encoded chunk buffer
5//! (including magic, headers, payload, and CRC trailer accounting).
6
7/// Maximum application payload bytes per wire chunk (excluding framing).
8pub const CHUNK_PAYLOAD_MAX: usize = 128;
9
10/// Used as a packet start identifier (SEcure SErial).
11pub const MAGIC_0: u8 = 0x5E;
12pub const MAGIC_1: u8 = 0x5E;
13pub const MAGIC: [u8; 2] = [MAGIC_0, MAGIC_1];
14pub const PACKET_DATA: u8 = 0xDA;
15pub const PACKET_ACK: u8 = 0xAC;
16/// Upper bound on the size of one fully encoded wire chunk (headers + payload + CRC), in bytes.
17pub const CHUNK_LEN_MAX: usize = 2 // MAGIC
18    + 1 // len
19    + 1 // type
20    + 2 // packet_id
21    + 4 // packet len
22    + 4 // chunk offset
23    + CHUNK_PAYLOAD_MAX // data
24    + 4; // crc
25
26/// Identifies which chunk of a packet the receiver has accepted (used in `ACK` wire frames).
27#[derive(Debug)]
28pub struct Ack {
29    pub(crate) packet_id: u16,
30    pub(crate) chunk_offset: u32,
31}
32
33impl Ack {
34    /// Serializes this ACK to six little-endian bytes (`packet_id`, `chunk_offset`).
35    pub fn to_buffer(&self) -> [u8; 6] {
36        let mut buffer = [0; 6];
37        buffer[0..2].copy_from_slice(&self.packet_id.to_le_bytes());
38        buffer[2..6].copy_from_slice(&self.chunk_offset.to_le_bytes());
39        buffer
40    }
41
42    /// Decodes [`Ack::to_buffer`] output.
43    pub fn from_buffer(buffer: [u8; 6]) -> Self {
44        let packet_id = u16::from_le_bytes(buffer[0..2].try_into().unwrap());
45        let chunk_offset = u32::from_le_bytes(buffer[2..6].try_into().unwrap());
46
47        Self {
48            packet_id,
49            chunk_offset,
50        }
51    }
52}