Skip to main content

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}