xmtp_api_d14n/protocol/traits/
visitor.rs

1use xmtp_proto::identity_v1::get_identity_updates_response::IdentityUpdateLog;
2use xmtp_proto::mls_v1::fetch_key_packages_response::KeyPackage;
3use xmtp_proto::mls_v1::subscribe_group_messages_request::Filter as SubscribeGroupMessagesFilter;
4use xmtp_proto::mls_v1::subscribe_welcome_messages_request::Filter as SubscribeWelcomeMessagesFilter;
5use xmtp_proto::xmtp::identity::api::v1::get_identity_updates_request;
6use xmtp_proto::xmtp::identity::associations::IdentityUpdate;
7use xmtp_proto::xmtp::mls::api::v1::GroupMessageInput;
8use xmtp_proto::xmtp::mls::api::v1::UploadKeyPackageRequest;
9use xmtp_proto::xmtp::mls::api::v1::WelcomeMessageInput;
10use xmtp_proto::xmtp::mls::api::v1::{
11    get_newest_group_message_response,
12    group_message::V1 as V3GroupMessage,
13    group_message_input::{V1 as GroupMessageV1, Version as GroupMessageVersion},
14    welcome_message::V1 as V3WelcomeMessage,
15    welcome_message::WelcomePointer as V3WelcomePointer,
16    welcome_message_input::{
17        V1 as WelcomeMessageV1, Version as WelcomeMessageVersion,
18        WelcomePointer as WelcomeMessageWelcomePointer,
19    },
20};
21use xmtp_proto::xmtp::xmtpv4::envelopes::{
22    ClientEnvelope, OriginatorEnvelope, PayerEnvelope, UnsignedOriginatorEnvelope,
23};
24use xmtp_proto::xmtp::xmtpv4::message_api::get_newest_envelope_response;
25
26use super::EnvelopeError;
27
28/// Envelope Visitor type for handling of serialized nested envelope types.
29///
30/// Envelope visitors allow implementors to define data needed from
31/// a [`ProtocolEnvelope`](super::ProtocolEnvelope).
32/// It is designed such that like-kinded types may be extracted in the same module. For instance,
33/// V3 and D14n Group Messages. A visitor is given to
34/// a ProtocolEnvelope implementation
35/// via the [`ProtocolEnvelope::accept`](super::ProtocolEnvelope::accept) method. The implementation of
36/// ProtocolEnvelope
37/// defines how the protobuf data structure is traversed. it is the responsibility of
38/// ProtocolEnvelope to call all relevant visitor methods defined on this trait.
39/// if a visitor is not called, it must not be present in the given input data of
40/// a ProtocolEnvelope
41///
42/// The [`Envelope`](super::Envelope) and [`EnvelopeCollection`](super::EnvelopeCollection) makes handling collections of
43/// [`ProtocolEnvelope`](super::ProtocolEnvelope) and applying their extractors more convenient, as
44/// it provides a blanket implementation on all [`ProtocolEnvelope`](super::ProtocolEnvelope)
45/// types.
46///
47/// The Aggregate Extractors, [`CollectionExtractor`](crate::protocol::extractors::CollectionExtractor) and
48/// [`SequencedExtractor`](crate::protocol::extractors::SequencedExtractor) applies an extractor to
49/// collections (Vec::<T>) of [`ProtocolEnvelope`](super::ProtocolEnvelope)'s.
50///
51/// # Examples
52///
53///### Run a single visitor
54/// ```
55/// # use xmtp_proto::mls_v1;
56/// # use xmtp_api_d14n::protocol::extractors::V3GroupMessageExtractor;
57/// # use xmtp_api_d14n::protocol::{ProtocolEnvelope, Extractor};
58/// // [`mls_v1::GroupMessage`] has a [`ProtocolEnvelope`] implementation.
59/// fn get_group_message(response: mls_v1::GroupMessage) -> xmtp_proto::types::GroupMessage {
60///     // our Extractor which has an implementation of [`EnvelopeVisitor`]
61///     let mut visitor = V3GroupMessageExtractor::default();
62///     response.accept(&mut visitor);
63///     let msg = visitor.get().unwrap();
64///     msg.unwrap()
65/// }
66/// ```
67/// ## Run multiple visitors
68/// Running multiple visitors is useful when you want to extract multiple things
69/// from an envelope, or it's uncertain whether the envelopes contains a certain type of message.
70/// Visitors chained as a tuple should always run through the protobuf message exactly once O(n).
71///
72/// _NOTE:_ the blanket implementation of [`Envelope`](super::Envelope) on all [`ProtocolEnvelope`](super::ProtocolEnvelope) types
73/// removes much of the boilerplate here, and can have functions added if needed.
74/// ```
75/// # use xmtp_proto::mls_v1;
76/// # use xmtp_proto::types::GroupMessage;
77/// # use xmtp_api_d14n::protocol::extractors::{TopicExtractor, PayloadExtractor};
78/// # use xmtp_api_d14n::protocol::{ProtocolEnvelope, Extractor};
79/// # use xmtp_proto::xmtp::xmtpv4::envelopes::OriginatorEnvelope;
80/// # fn get_topic_and_payload(envelope: OriginatorEnvelope) {
81///     let topic = TopicExtractor::default();
82///     let payload = PayloadExtractor::default();
83///     let mut visitor = (topic, payload);
84///     envelope.accept(&mut visitor);
85///     // unwrap the visitor from its tuple
86///     let (topic, payload) = visitor;
87///     let topic = topic.get().unwrap();
88///     let payload = payload.get().unwrap();
89/// # }
90/// ```
91pub trait EnvelopeVisitor<'env> {
92    type Error: Into<EnvelopeError>;
93    /// Visit the OriginatorEnvelope Type
94    fn visit_originator(&mut self, _e: &OriginatorEnvelope) -> Result<(), Self::Error> {
95        Ok(())
96    }
97    /// Visit the UnsignedOriginatorEnvelope type
98    fn visit_unsigned_originator(
99        &mut self,
100        _e: &UnsignedOriginatorEnvelope,
101    ) -> Result<(), Self::Error> {
102        Ok(())
103    }
104    /// Visit the Payer Envelope Type
105    fn visit_payer(&mut self, _e: &PayerEnvelope) -> Result<(), Self::Error> {
106        Ok(())
107    }
108    /// Visit the ClientEnvelope type
109    fn visit_client(&mut self, _e: &ClientEnvelope) -> Result<(), Self::Error> {
110        Ok(())
111    }
112    /// Visit the GroupMessageVersion type
113    fn visit_group_message_version(&mut self, _m: &GroupMessageVersion) -> Result<(), Self::Error> {
114        Ok(())
115    }
116    /// Visit the GroupMessageInput containing the welcome message version
117    fn visit_group_message_input(&mut self, _m: &GroupMessageInput) -> Result<(), Self::Error> {
118        Ok(())
119    }
120
121    /// Visit a V1 Group Message
122    fn visit_group_message_v1(&mut self, _m: &GroupMessageV1) -> Result<(), Self::Error> {
123        Ok(())
124    }
125    /// Visit the WelcomeMessageInput containing the welcome message version
126    fn visit_welcome_message_version(
127        &mut self,
128        _m: &WelcomeMessageVersion,
129    ) -> Result<(), Self::Error> {
130        Ok(())
131    }
132    /// Visit the WelcomeMessageInput containing the welcome message version
133    fn visit_welcome_message_input(&mut self, _m: &WelcomeMessageInput) -> Result<(), Self::Error> {
134        Ok(())
135    }
136
137    /// Visit a V1 Welcome Message
138    fn visit_welcome_message_v1(&mut self, _m: &WelcomeMessageV1) -> Result<(), Self::Error> {
139        Ok(())
140    }
141
142    /// Visit a Welcome Pointer
143    fn visit_welcome_pointer(
144        &mut self,
145        _m: &WelcomeMessageWelcomePointer,
146    ) -> Result<(), Self::Error> {
147        Ok(())
148    }
149
150    fn visit_v3_group_message(&mut self, _m: &V3GroupMessage) -> Result<(), Self::Error> {
151        Ok(())
152    }
153
154    fn visit_v3_welcome_message(&mut self, _m: &V3WelcomeMessage) -> Result<(), Self::Error> {
155        Ok(())
156    }
157
158    fn visit_v3_welcome_pointer(&mut self, _m: &V3WelcomePointer) -> Result<(), Self::Error> {
159        Ok(())
160    }
161
162    /// Visit the Upload Key Package
163    fn visit_upload_key_package(
164        &mut self,
165        _p: &UploadKeyPackageRequest,
166    ) -> Result<(), Self::Error> {
167        Ok(())
168    }
169
170    /// Visit the Identity Update Type
171    fn visit_identity_update(&mut self, _u: &IdentityUpdate) -> Result<(), Self::Error> {
172        Ok(())
173    }
174
175    fn visit_identity_update_log(&mut self, _u: &IdentityUpdateLog) -> Result<(), Self::Error> {
176        Ok(())
177    }
178
179    /// Visit an Identity Updates Request
180    fn visit_identity_updates_request(
181        &mut self,
182        _u: &get_identity_updates_request::Request,
183    ) -> Result<(), Self::Error> {
184        Ok(())
185    }
186
187    fn visit_key_package(&mut self, _k: &KeyPackage) -> Result<(), Self::Error> {
188        Ok(())
189    }
190
191    /// Visit an empty type in a fixed-length array
192    /// Useful is client expects a constant length between
193    /// requests and responses
194    fn visit_none(&mut self) -> Result<(), Self::Error> {
195        Ok(())
196    }
197
198    /// Visit a Newest Envelope Response
199    fn visit_newest_envelope_response(
200        &mut self,
201        _u: &get_newest_envelope_response::Response,
202    ) -> Result<(), Self::Error> {
203        Ok(())
204    }
205
206    /// visit_subscribe_group_messages_request
207    fn visit_subscribe_group_messages_request(
208        &mut self,
209        _r: &SubscribeGroupMessagesFilter,
210    ) -> Result<(), Self::Error> {
211        Ok(())
212    }
213
214    /// visit_subscribe_group_messages_request
215    fn visit_subscribe_welcome_messages_request(
216        &mut self,
217        _r: &SubscribeWelcomeMessagesFilter,
218    ) -> Result<(), Self::Error> {
219        Ok(())
220    }
221
222    fn visit_newest_group_message_response(
223        &mut self,
224        _u: &get_newest_group_message_response::Response,
225    ) -> Result<(), Self::Error> {
226        Ok(())
227    }
228
229    #[cfg(any(test, feature = "test-utils"))]
230    fn test_visit_u32(&mut self, _n: &u32) -> Result<(), Self::Error> {
231        Ok(())
232    }
233}