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}