74 lines
2.3 KiB
Rust
74 lines
2.3 KiB
Rust
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<u8>,
|
|
}
|
|
impl MessageFrame {
|
|
pub fn new(message_type: u16, message_version: u16, payload: Vec<u8>) -> 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<Vec<u8>> {
|
|
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<u8>) -> MessageFrame {
|
|
MessageFrame::new(message.message_type(), message.message_version(), payload)
|
|
}
|
|
}
|