net/adapter/net/cortex/envelope.rs
1//! `EventEnvelope` + `IntoRedexPayload` — the handoff from caller code
2//! to the CortEX adapter's ingest path.
3//!
4//! The adapter is agnostic to what's inside the payload tail. It only
5//! requires that a caller type can project itself into
6//! `(EventMeta, Bytes)`. Implementations define how their domain
7//! objects map onto the 20-byte header + type-specific bytes.
8//!
9//! A default [`EventEnvelope`] is provided for callers that already
10//! have the `(meta, payload)` pair in hand. CortEX's own richer
11//! envelope type (defined in CortEX's plan, not here) will implement
12//! [`IntoRedexPayload`] directly.
13
14use bytes::Bytes;
15
16use super::meta::EventMeta;
17
18/// Project a caller type into a RedEX payload.
19///
20/// Implementations return `(meta, tail)`. The adapter concatenates the
21/// 20-byte meta with the tail and appends the result to RedEX.
22pub trait IntoRedexPayload {
23 /// Consume `self` and return the `(meta, tail)` pair.
24 fn into_redex_payload(self) -> (EventMeta, Bytes);
25}
26
27/// A straightforward envelope pairing an [`EventMeta`] with its
28/// payload tail. Use this when CortEX's richer envelope type is not
29/// needed (tests, simple callers, the v1 adapter wire-up).
30#[derive(Debug, Clone)]
31pub struct EventEnvelope {
32 /// The 20-byte header that will land at the start of the RedEX
33 /// payload.
34 pub meta: EventMeta,
35 /// Type-specific bytes following the header.
36 pub payload: Bytes,
37}
38
39impl EventEnvelope {
40 /// Build an envelope from a header and any byte-like payload.
41 pub fn new(meta: EventMeta, payload: impl Into<Bytes>) -> Self {
42 Self {
43 meta,
44 payload: payload.into(),
45 }
46 }
47}
48
49impl IntoRedexPayload for EventEnvelope {
50 fn into_redex_payload(self) -> (EventMeta, Bytes) {
51 (self.meta, self.payload)
52 }
53}
54
55/// Convenience impl: a `(meta, tail)` tuple projects trivially.
56impl IntoRedexPayload for (EventMeta, Bytes) {
57 fn into_redex_payload(self) -> (EventMeta, Bytes) {
58 self
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_envelope_into_payload_roundtrip() {
68 let meta = EventMeta::new(0x10, 0, 0xAA, 1, 0xBB);
69 let tail = Bytes::from_static(b"hello");
70 let env = EventEnvelope::new(meta, tail.clone());
71 let (meta_out, tail_out) = env.into_redex_payload();
72 assert_eq!(meta_out, meta);
73 assert_eq!(tail_out, tail);
74 }
75
76 #[test]
77 fn test_tuple_impl() {
78 let meta = EventMeta::new(0, 0, 0, 0, 0);
79 let tail = Bytes::from_static(b"x");
80 let (m, t) = (meta, tail.clone()).into_redex_payload();
81 assert_eq!(m, meta);
82 assert_eq!(t, tail);
83 }
84}