Skip to main content

xmtp_proto/types/
received_envelope.rs

1//! Receive-only response views that retain each `ServerEnvelope` as received.
2//! Decoding a generated struct drops unknown fields; these views keep the bytes.
3use crate::backend_v1 as wire;
4use bytes::Bytes;
5use prost::Message;
6
7/// One backend envelope: its exact received bytes and decoded metadata.
8#[derive(Clone, Debug, PartialEq)]
9pub struct ReceivedEnvelope {
10    meta: Option<wire::EnvelopeMeta>,
11    raw: Bytes,
12}
13
14impl ReceivedEnvelope {
15    /// Decode the complete envelope to validate it, and keep its bytes unchanged.
16    /// Copy them so a retained envelope does not keep its whole response frame alive.
17    pub fn from_raw(raw: Bytes) -> Result<Self, prost::DecodeError> {
18        let decoded = wire::ServerEnvelope::decode(raw.as_ref())?;
19        Ok(Self {
20            meta: decoded.meta,
21            raw: Bytes::copy_from_slice(&raw),
22        })
23    }
24
25    pub fn meta(&self) -> Option<&wire::EnvelopeMeta> {
26        self.meta.as_ref()
27    }
28
29    /// The serialized `ServerEnvelope` exactly as the backend sent it.
30    pub fn raw(&self) -> &Bytes {
31        &self.raw
32    }
33
34    /// Decode the complete envelope for processing. Unknown fields are dropped.
35    pub fn decode(&self) -> Result<wire::ServerEnvelope, crate::ConversionError> {
36        Ok(wire::ServerEnvelope::decode(self.raw.clone())?)
37    }
38}
39
40/// Decode a repeated raw envelope field.
41pub fn received_envelopes(raw: Vec<Bytes>) -> Result<Vec<ReceivedEnvelope>, prost::DecodeError> {
42    raw.into_iter().map(ReceivedEnvelope::from_raw).collect()
43}
44
45/// `QueryResponse` with raw envelopes. Tags match `backend.proto`.
46#[derive(Clone, PartialEq, Message)]
47pub struct ReceivedQueryResponse {
48    #[prost(bytes = "bytes", repeated, tag = "1")]
49    pub envelopes: Vec<Bytes>,
50    #[prost(message, optional, tag = "2")]
51    pub continuation: Option<wire::Continuation>,
52}
53
54/// `Messages` from `SubscribeStaticResponse` or `SubscribeResponse`.
55#[derive(Clone, PartialEq, Message)]
56pub struct ReceivedMessages {
57    #[prost(bytes = "bytes", repeated, tag = "1")]
58    pub envelopes: Vec<Bytes>,
59}
60
61/// `SubscribeStaticResponse` with raw envelopes. Tags match `backend.proto`.
62#[derive(Clone, PartialEq, Message)]
63pub struct ReceivedStaticResponse {
64    #[prost(oneof = "ReceivedStaticFrame", tags = "1, 2, 3")]
65    pub response: Option<ReceivedStaticFrame>,
66}
67
68#[derive(Clone, PartialEq, prost::Oneof)]
69pub enum ReceivedStaticFrame {
70    #[prost(message, tag = "1")]
71    Started(wire::subscribe_static_response::Started),
72    #[prost(message, tag = "2")]
73    Messages(ReceivedMessages),
74    #[prost(message, tag = "3")]
75    Keepalive(wire::subscribe_static_response::Keepalive),
76}
77
78/// `SubscribeResponse` with raw envelopes. Tags match `backend.proto`.
79#[derive(Clone, PartialEq, Message)]
80pub struct ReceivedSubscribeResponse {
81    #[prost(oneof = "ReceivedSubscribeFrame", tags = "1, 2, 3, 4, 5")]
82    pub response: Option<ReceivedSubscribeFrame>,
83}
84
85#[derive(Clone, PartialEq, prost::Oneof)]
86pub enum ReceivedSubscribeFrame {
87    #[prost(message, tag = "1")]
88    Started(wire::subscribe_response::Started),
89    #[prost(message, tag = "2")]
90    Applied(wire::subscribe_response::Applied),
91    #[prost(message, tag = "3")]
92    Messages(ReceivedMessages),
93    #[prost(message, tag = "4")]
94    Ping(wire::Ping),
95    #[prost(message, tag = "5")]
96    Pong(wire::Pong),
97}
98
99xmtp_common::if_test! {
100    /// A Welcome `ServerEnvelope` whose `WelcomeMessage` holds only `variant`
101    /// under tag 3, which this schema does not define. Prost cannot build it.
102    pub fn future_welcome_envelope(meta: &wire::EnvelopeMeta, variant: &[u8]) -> Bytes {
103        use prost::encoding::{bytes, message};
104        let (mut welcome, mut client, mut server) = (Vec::new(), Vec::new(), Vec::new());
105        bytes::encode(3, &variant.to_vec(), &mut welcome);
106        bytes::encode(2, &welcome, &mut client);
107        message::encode(1, meta, &mut server);
108        bytes::encode(2, &client, &mut server);
109        server.into()
110    }
111
112    /// Equal when the received bytes are the canonical encoding of `other`.
113    impl PartialEq<wire::ServerEnvelope> for ReceivedEnvelope {
114        fn eq(&self, other: &wire::ServerEnvelope) -> bool {
115            self.raw == other.encode_to_vec()
116        }
117    }
118
119    impl From<wire::ServerEnvelope> for ReceivedEnvelope {
120        fn from(envelope: wire::ServerEnvelope) -> Self {
121            Self { meta: envelope.meta.clone(), raw: envelope.encode_to_vec().into() }
122        }
123    }
124
125    impl From<wire::QueryResponse> for ReceivedQueryResponse {
126        fn from(response: wire::QueryResponse) -> Self {
127            Self {
128                envelopes: response.envelopes.iter().map(|e| e.encode_to_vec().into()).collect(),
129                continuation: response.continuation,
130            }
131        }
132    }
133
134    impl From<wire::SubscribeResponse> for ReceivedSubscribeResponse {
135        fn from(response: wire::SubscribeResponse) -> Self {
136            Self::decode(response.encode_to_vec().as_slice()).expect("same tags")
137        }
138    }
139}