scroll.server/crates/titan/src/frame.rs
WiseDev d25a6de423 move all crates into crates/, glob members
pure move, no code touched. readme and protocol.md paths fixed up.
2026-08-23 08:15:45 +03:00

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)
}
}