wsprism_core/protocol/
hot.rs

1//! Hot Lane binary frame parsing (panic-free).
2//!
3//! Parsing rules:
4//! - Never index (`buf[0]`); always use `Buf` and `remaining()` checks.
5//! - Never `unwrap()` / `expect()` / `panic!()` in production paths.
6//! - Validate header lengths before reading optional fields.
7
8use bytes::Buf;
9use bytes::Bytes;
10
11use crate::error::{Result, WsPrismError};
12
13/// Hot Lane flag: seq (u32) is present.
14pub const HOT_FLAG_SEQ_PRESENT: u8 = 0x01;
15
16/// Parsed Hot Lane frame.
17#[derive(Debug, Clone)]
18pub struct HotFrame {
19    /// Protocol version (must be 1).
20    pub v: u8,
21    /// Service id (routes to native BinaryService).
22    pub svc_id: u8,
23    /// Opcode within that service.
24    pub opcode: u8,
25    /// Feature flags (u8).
26    pub flags: u8,
27    /// Optional sequence number.
28    pub seq: Option<u32>,
29    /// Opaque payload (zero-copy).
30    pub payload: Bytes,
31}
32
33/// Decode a Hot Lane frame from bytes.
34///
35/// Defensive against malformed input; returns structured errors instead of
36/// panicking on short buffers or unsupported versions.
37pub fn decode_hot_frame(mut buf: Bytes) -> Result<HotFrame> {
38    // Minimum header: v, svc_id, opcode, flags
39    if buf.remaining() < 4 {
40        return Err(WsPrismError::BadRequest("hot frame too short".into()));
41    }
42
43    let v = buf.get_u8();
44    if v != 1 {
45        return Err(WsPrismError::UnsupportedVersion);
46    }
47
48    let svc_id = buf.get_u8();
49    let opcode = buf.get_u8();
50    let flags = buf.get_u8();
51
52    let seq = if (flags & HOT_FLAG_SEQ_PRESENT) != 0 {
53        if buf.remaining() < 4 {
54            return Err(WsPrismError::BadRequest(
55                "seq flag set but missing u32".into(),
56            ));
57        }
58        Some(buf.get_u32_le())
59    } else {
60        None
61    };
62
63    // Remaining bytes are payload.
64    let payload = buf.copy_to_bytes(buf.remaining());
65
66    Ok(HotFrame {
67        v,
68        svc_id,
69        opcode,
70        flags,
71        seq,
72        payload,
73    })
74}