rapace_core/frame.rs
1//! Frame types for sending and receiving.
2
3use crate::MsgDescHot;
4
5/// Owned frame for sending or storage.
6#[derive(Debug, Clone)]
7pub struct Frame {
8 /// The frame descriptor.
9 pub desc: MsgDescHot,
10 /// Optional payload (None if inline or empty).
11 pub payload: Option<Vec<u8>>,
12}
13
14impl Frame {
15 /// Create a new frame with the given descriptor.
16 pub fn new(desc: MsgDescHot) -> Self {
17 Self {
18 desc,
19 payload: None,
20 }
21 }
22
23 /// Create a frame with inline payload.
24 pub fn with_inline_payload(mut desc: MsgDescHot, payload: &[u8]) -> Option<Self> {
25 if payload.len() > crate::INLINE_PAYLOAD_SIZE {
26 return None;
27 }
28 desc.payload_slot = crate::INLINE_PAYLOAD_SLOT;
29 desc.payload_generation = 0;
30 desc.payload_offset = 0;
31 desc.payload_len = payload.len() as u32;
32 desc.inline_payload[..payload.len()].copy_from_slice(payload);
33 Some(Self {
34 desc,
35 payload: None,
36 })
37 }
38
39 /// Create a frame with external payload.
40 ///
41 /// Note: For owned frames with external payload, we use a sentinel slot value (0)
42 /// to distinguish from inline. The actual slot is only meaningful for SHM transport.
43 pub fn with_payload(mut desc: MsgDescHot, payload: Vec<u8>) -> Self {
44 // Mark as non-inline by setting slot to 0 (or any non-MAX value)
45 // This is a sentinel for "payload is in the Frame::payload field"
46 desc.payload_slot = 0;
47 desc.payload_len = payload.len() as u32;
48 Self {
49 desc,
50 payload: Some(payload),
51 }
52 }
53
54 /// Get the payload bytes.
55 pub fn payload(&self) -> &[u8] {
56 if self.desc.is_inline() {
57 self.desc.inline_payload()
58 } else {
59 self.payload.as_deref().unwrap_or(&[])
60 }
61 }
62}
63
64/// Borrowed view of a frame for zero-copy receive.
65///
66/// Lifetime is tied to the receive call that produced it.
67/// Caller must process or copy before calling recv_frame again.
68#[derive(Debug)]
69pub struct FrameView<'a> {
70 /// Reference to the frame descriptor.
71 pub desc: &'a MsgDescHot,
72 /// Reference to the payload bytes.
73 pub payload: &'a [u8],
74}
75
76impl<'a> FrameView<'a> {
77 /// Create a new frame view.
78 pub fn new(desc: &'a MsgDescHot, payload: &'a [u8]) -> Self {
79 Self { desc, payload }
80 }
81
82 /// Convert to an owned Frame (copies payload if needed).
83 pub fn to_owned(&self) -> Frame {
84 if self.desc.is_inline() {
85 Frame {
86 desc: *self.desc,
87 payload: None,
88 }
89 } else {
90 Frame {
91 desc: *self.desc,
92 payload: Some(self.payload.to_vec()),
93 }
94 }
95 }
96}