use crate::error::{Error, Result}; use crate::message::Message; pub const HEADER_LEN: usize = 7; pub const MAX_PAYLOAD_LEN: usize = 0x00FF_FFFF; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct FrameHeader { pub message_type: u16, pub payload_len: usize, pub message_version: u16, } impl FrameHeader { pub fn parse(bytes: &[u8; HEADER_LEN]) -> Self { Self { message_type: u16::from_be_bytes([bytes[0], bytes[1]]), payload_len: ((bytes[2] as usize) << 16) | ((bytes[3] as usize) << 8) | bytes[4] as usize, message_version: u16::from_be_bytes([bytes[5], bytes[6]]), } } pub fn to_bytes(self) -> [u8; HEADER_LEN] { let ty = self.message_type.to_be_bytes(); let version = self.message_version.to_be_bytes(); [ ty[0], ty[1], (self.payload_len >> 16) as u8, (self.payload_len >> 8) as u8, self.payload_len as u8, version[0], version[1], ] } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct MessageFrame { pub message_type: u16, pub message_version: u16, pub payload: Vec, } impl MessageFrame { pub fn new(message_type: u16, message_version: u16, payload: Vec) -> Self { Self { message_type, message_version, payload, } } pub fn header(&self) -> FrameHeader { FrameHeader { message_type: self.message_type, payload_len: self.payload.len(), message_version: self.message_version, } } } pub struct FrameCodec; impl FrameCodec { pub fn encode(frame: &MessageFrame) -> Result> { if frame.payload.len() > MAX_PAYLOAD_LEN { return Err(Error::FrameTooLarge { actual: frame.payload.len(), limit: MAX_PAYLOAD_LEN, }); } let mut out = Vec::with_capacity(HEADER_LEN + frame.payload.len()); out.extend_from_slice(&frame.header().to_bytes()); out.extend_from_slice(&frame.payload); Ok(out) } pub fn frame_of(message: &dyn Message, payload: Vec) -> MessageFrame { MessageFrame::new(message.message_type(), message.message_version(), payload) } }