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}