xmtp_api_d14n/protocol/impls/
protocol_envelopes.rs

1//! Implementations of traits
2use crate::protocol::EnvelopeCollection;
3
4use crate::protocol::traits::{EnvelopeError, EnvelopeVisitor, Extractor, ProtocolEnvelope};
5use prost::Message;
6use xmtp_proto::identity_v1::get_identity_updates_response::IdentityUpdateLog;
7use xmtp_proto::mls_v1::fetch_key_packages_response::KeyPackage;
8use xmtp_proto::mls_v1::subscribe_group_messages_request::Filter as SubscribeGroupMessagesFilter;
9use xmtp_proto::mls_v1::subscribe_welcome_messages_request::Filter as SubscribeWelcomeMessagesFilter;
10use xmtp_proto::mls_v1::{
11    SubscribeGroupMessagesRequest, SubscribeWelcomeMessagesRequest, welcome_message,
12};
13use xmtp_proto::types::{Cursor, OrphanedEnvelope, Topic};
14use xmtp_proto::xmtp::xmtpv4::message_api::{
15    SubscribeEnvelopesResponse, get_newest_envelope_response,
16};
17use xmtp_proto::{
18    ConversionError,
19    xmtp::identity::{api::v1::get_identity_updates_request, associations::IdentityUpdate},
20    xmtp::mls::api::v1::UploadKeyPackageRequest,
21    xmtp::mls::api::v1::{
22        GroupMessage as V3ProtoGroupMessage, GroupMessageInput,
23        WelcomeMessage as V3ProtoWelcomeMessage, WelcomeMessageInput, group_message,
24        group_message_input::Version as GroupMessageVersion,
25        welcome_message_input::Version as WelcomeMessageVersion,
26    },
27    xmtp::xmtpv4::envelopes::client_envelope::Payload,
28    xmtp::xmtpv4::envelopes::{
29        ClientEnvelope, OriginatorEnvelope, PayerEnvelope, UnsignedOriginatorEnvelope,
30    },
31};
32
33impl<'env> ProtocolEnvelope<'env> for OriginatorEnvelope {
34    type Nested<'a> = UnsignedOriginatorEnvelope;
35
36    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
37    where
38        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
39    {
40        visitor.visit_originator(self)?;
41        let unsigned = self.get_nested()?;
42        unsigned.accept(visitor)?;
43        Ok(())
44    }
45
46    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
47        Ok(UnsignedOriginatorEnvelope::decode(
48            self.unsigned_originator_envelope.as_slice(),
49        )?)
50    }
51}
52
53impl<'env> ProtocolEnvelope<'env> for UnsignedOriginatorEnvelope {
54    type Nested<'a> = PayerEnvelope;
55    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
56    where
57        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
58    {
59        visitor.visit_unsigned_originator(self)?;
60        let payer = self.get_nested()?;
61        payer.accept(visitor)?;
62        Ok(())
63    }
64
65    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
66        Ok(PayerEnvelope::decode(self.payer_envelope_bytes.as_slice())?)
67    }
68}
69
70impl<'env> ProtocolEnvelope<'env> for PayerEnvelope {
71    type Nested<'a> = ClientEnvelope;
72
73    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
74    where
75        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
76    {
77        visitor.visit_payer(self)?;
78        let client = self.get_nested()?;
79        client.accept(visitor)?;
80        Ok(())
81    }
82
83    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
84        Ok(ClientEnvelope::decode(
85            self.unsigned_client_envelope.as_slice(),
86        )?)
87    }
88}
89
90impl<'env> ProtocolEnvelope<'env>
91    for xmtp_proto::mls_v1::get_newest_group_message_response::Response
92{
93    type Nested<'a> = ();
94
95    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
96    where
97        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
98    {
99        visitor.visit_newest_group_message_response(self)?;
100        Ok(())
101    }
102
103    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
104        Ok(())
105    }
106}
107
108impl<'env> ProtocolEnvelope<'env> for ClientEnvelope {
109    type Nested<'a> = Option<&'a Payload>;
110
111    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
112    where
113        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
114    {
115        visitor.visit_client(self)?;
116        self.get_nested()?.accept(visitor)?;
117        Ok(())
118    }
119
120    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
121        // TODO: if Payload being missing needs to be handled, we
122        // should return an error here and modify the type of Nested.
123        Ok(self.payload.as_ref())
124    }
125}
126
127impl<'env> ProtocolEnvelope<'env> for Payload {
128    type Nested<'a> = ();
129
130    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
131    where
132        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
133    {
134        match self {
135            Payload::GroupMessage(msg) => msg.accept(visitor)?,
136            Payload::WelcomeMessage(msg) => msg.accept(visitor)?,
137            Payload::UploadKeyPackage(msg) => msg.accept(visitor)?,
138            Payload::IdentityUpdate(msg) => msg.accept(visitor)?,
139            Payload::PayerReport(_) => {
140                tracing::warn!("Payload::PayerReport type not handled in client");
141                return Ok(());
142            }
143            Payload::PayerReportAttestation(_) => {
144                tracing::warn!("Payload::PayerReportAttestation type not handled in client");
145                return Ok(());
146            }
147        };
148        Ok(())
149    }
150
151    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
152        Ok(())
153    }
154}
155
156impl<'env> ProtocolEnvelope<'env> for GroupMessageInput {
157    type Nested<'a> = Option<&'a GroupMessageVersion>;
158
159    fn accept<'a, V: EnvelopeVisitor<'env>>(&'a self, visitor: &mut V) -> Result<(), EnvelopeError>
160    where
161        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
162    {
163        visitor.visit_group_message_input(self)?;
164        if let Some(versioned) = self.get_nested()? {
165            versioned.accept(visitor)?;
166        }
167        Ok(())
168    }
169
170    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
171        // TODO: if GroupMessageVersion being missing needs  to be handled, we
172        // should return an error here.
173        Ok(self.version.as_ref())
174    }
175}
176
177// TODO(cvoell): impl<'env> ProtocolEnvelope<'env> for BatchPublishCommitLogRequest {
178
179impl<'env> ProtocolEnvelope<'env> for GroupMessageVersion {
180    type Nested<'a> = ();
181
182    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
183    where
184        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
185    {
186        visitor.visit_group_message_version(self)?;
187        match self {
188            GroupMessageVersion::V1(v1) => visitor.visit_group_message_v1(v1),
189        }?;
190        Ok(())
191    }
192
193    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
194        Ok(())
195    }
196}
197
198impl<'env> ProtocolEnvelope<'env> for WelcomeMessageInput {
199    type Nested<'a> = Option<&'a WelcomeMessageVersion>;
200
201    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
202    where
203        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
204    {
205        visitor.visit_welcome_message_input(self)?;
206        self.get_nested()?.accept(visitor)?;
207        Ok(())
208    }
209
210    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
211        // TODO: if WelcomeMessageVersion being missing needs  to be handled, we
212        // should return an error here and modify the return type of Nested
213        Ok(self.version.as_ref())
214    }
215}
216
217impl<'env> ProtocolEnvelope<'env> for WelcomeMessageVersion {
218    type Nested<'a> = ();
219
220    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
221    where
222        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
223    {
224        visitor.visit_welcome_message_version(self)?;
225        match self {
226            WelcomeMessageVersion::V1(v1) => visitor.visit_welcome_message_v1(v1)?,
227            WelcomeMessageVersion::WelcomePointer(wp) => visitor.visit_welcome_pointer(wp)?,
228        }
229        Ok(())
230    }
231
232    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
233        Ok(())
234    }
235}
236
237impl<'env> ProtocolEnvelope<'env> for UploadKeyPackageRequest {
238    type Nested<'a> = ();
239
240    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
241    where
242        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
243    {
244        visitor.visit_upload_key_package(self)?;
245        self.get_nested()?.accept(visitor)?;
246        Ok(())
247    }
248
249    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
250        Ok(())
251    }
252}
253
254impl<'env> ProtocolEnvelope<'env> for IdentityUpdate {
255    type Nested<'a> = ();
256
257    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
258    where
259        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
260    {
261        visitor.visit_identity_update(self)?;
262        self.get_nested()?.accept(visitor)?;
263        Ok(())
264    }
265
266    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
267        Ok(())
268    }
269}
270
271impl<'env> ProtocolEnvelope<'env> for get_identity_updates_request::Request {
272    type Nested<'a> = ();
273
274    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
275    where
276        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
277    {
278        visitor.visit_identity_updates_request(self)?;
279        self.get_nested()?.accept(visitor)?;
280        Ok(())
281    }
282
283    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
284        Ok(())
285    }
286}
287
288impl<'env> ProtocolEnvelope<'env> for KeyPackage {
289    type Nested<'a> = ();
290
291    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
292    where
293        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
294    {
295        visitor.visit_key_package(self)?;
296        self.get_nested()?.accept(visitor)?;
297        Ok(())
298    }
299
300    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
301        Ok(())
302    }
303}
304
305impl<'env> ProtocolEnvelope<'env> for get_newest_envelope_response::Response {
306    type Nested<'a> = Option<&'a OriginatorEnvelope>;
307
308    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
309    where
310        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
311    {
312        visitor.visit_newest_envelope_response(self)?;
313        self.get_nested()?.accept(visitor)?;
314        Ok(())
315    }
316
317    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
318        Ok(self.originator_envelope.as_ref())
319    }
320}
321
322impl<'env, T> ProtocolEnvelope<'env> for Option<&T>
323where
324    T: ProtocolEnvelope<'env>,
325{
326    type Nested<'a>
327        = ()
328    where
329        Self: 'a;
330
331    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
332    where
333        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
334    {
335        match self {
336            Some(o) => o.accept(visitor),
337            None => Ok(visitor.visit_none()?),
338        }
339    }
340
341    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
342        Ok(())
343    }
344}
345
346impl<'env> ProtocolEnvelope<'env> for SubscribeGroupMessagesFilter {
347    type Nested<'a> = ();
348
349    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
350    where
351        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
352    {
353        visitor.visit_subscribe_group_messages_request(self)?;
354        Ok(())
355    }
356
357    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
358        Ok(())
359    }
360}
361
362impl<'env> ProtocolEnvelope<'env> for SubscribeWelcomeMessagesFilter {
363    type Nested<'a> = ();
364
365    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
366    where
367        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
368    {
369        visitor.visit_subscribe_welcome_messages_request(self)?;
370        Ok(())
371    }
372
373    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
374        Ok(())
375    }
376}
377
378impl<'env> ProtocolEnvelope<'env> for V3ProtoGroupMessage {
379    type Nested<'a> = Option<&'a group_message::Version>;
380
381    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
382    where
383        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
384    {
385        self.get_nested()?.accept(visitor)
386    }
387
388    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
389        Ok(self.version.as_ref())
390    }
391}
392
393impl<'env> ProtocolEnvelope<'env> for group_message::Version {
394    type Nested<'a> = ();
395
396    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
397    where
398        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
399    {
400        match self {
401            group_message::Version::V1(v1) => visitor.visit_v3_group_message(v1)?,
402        }
403        Ok(())
404    }
405
406    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
407        Ok(())
408    }
409}
410
411impl<'env> ProtocolEnvelope<'env> for V3ProtoWelcomeMessage {
412    type Nested<'a> = Option<&'a welcome_message::Version>;
413
414    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
415    where
416        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
417    {
418        self.get_nested()?.accept(visitor)
419    }
420
421    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
422        Ok(self.version.as_ref())
423    }
424}
425
426impl<'env> ProtocolEnvelope<'env> for welcome_message::Version {
427    type Nested<'a> = ();
428
429    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
430    where
431        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
432    {
433        match self {
434            welcome_message::Version::V1(v1) => visitor.visit_v3_welcome_message(v1)?,
435            welcome_message::Version::WelcomePointer(wp) => visitor.visit_v3_welcome_pointer(wp)?,
436        }
437        Ok(())
438    }
439
440    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
441        Ok(())
442    }
443}
444
445impl<'env> ProtocolEnvelope<'env> for IdentityUpdateLog {
446    type Nested<'a> = Option<&'a IdentityUpdate>;
447
448    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
449    where
450        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
451    {
452        visitor.visit_identity_update_log(self)?;
453        self.get_nested()?.accept(visitor)
454    }
455
456    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
457        Ok(self.update.as_ref())
458    }
459}
460
461impl<'env> ProtocolEnvelope<'env> for () {
462    type Nested<'a> = ();
463
464    fn accept<V: EnvelopeVisitor<'env>>(&self, _: &mut V) -> Result<(), EnvelopeError>
465    where
466        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
467    {
468        Ok(())
469    }
470
471    fn get_nested(&self) -> Result<Self::Nested<'_>, ConversionError> {
472        Ok(())
473    }
474}
475
476impl EnvelopeCollection<'_> for SubscribeEnvelopesResponse {
477    fn topics(&self) -> Result<Vec<Topic>, EnvelopeError> {
478        self.envelopes.topics()
479    }
480
481    fn cursors(&self) -> Result<Vec<Cursor>, EnvelopeError> {
482        self.envelopes.cursors()
483    }
484
485    fn payloads(&self) -> Result<Vec<Payload>, EnvelopeError> {
486        self.envelopes.payloads()
487    }
488
489    fn sha256_hashes(&self) -> Result<Vec<Vec<u8>>, EnvelopeError> {
490        self.envelopes.sha256_hashes()
491    }
492
493    fn client_envelopes(&self) -> Result<Vec<ClientEnvelope>, EnvelopeError> {
494        self.envelopes.client_envelopes()
495    }
496
497    fn len(&self) -> usize {
498        self.envelopes.len()
499    }
500
501    fn is_empty(&self) -> bool {
502        self.envelopes.is_empty()
503    }
504
505    fn consume<E>(self) -> Result<Vec<<E as Extractor>::Output>, EnvelopeError>
506    where
507        for<'a> E: Default + Extractor + EnvelopeVisitor<'a>,
508        Self: Clone,
509        for<'a> EnvelopeError: From<<E as EnvelopeVisitor<'a>>::Error>,
510        Self: Sized,
511    {
512        self.envelopes.consume::<E>()
513    }
514
515    fn group_messages(
516        &self,
517    ) -> Result<Vec<Option<xmtp_proto::types::GroupMessage>>, EnvelopeError> {
518        self.envelopes.group_messages()
519    }
520
521    fn welcome_messages(
522        &self,
523    ) -> Result<Vec<Option<xmtp_proto::types::WelcomeMessage>>, EnvelopeError> {
524        self.envelopes.welcome_messages()
525    }
526
527    fn orphans(&self) -> Result<Vec<OrphanedEnvelope>, EnvelopeError> {
528        self.envelopes.orphans()
529    }
530}
531
532impl EnvelopeCollection<'_> for SubscribeGroupMessagesRequest {
533    fn topics(&self) -> Result<Vec<Topic>, EnvelopeError> {
534        self.filters.topics()
535    }
536
537    fn cursors(&self) -> Result<Vec<Cursor>, EnvelopeError> {
538        self.filters.cursors()
539    }
540
541    fn payloads(&self) -> Result<Vec<Payload>, EnvelopeError> {
542        self.filters.payloads()
543    }
544
545    fn sha256_hashes(&self) -> Result<Vec<Vec<u8>>, EnvelopeError> {
546        self.filters.sha256_hashes()
547    }
548
549    fn client_envelopes(&self) -> Result<Vec<ClientEnvelope>, EnvelopeError> {
550        self.filters.client_envelopes()
551    }
552
553    fn len(&self) -> usize {
554        self.filters.len()
555    }
556
557    fn is_empty(&self) -> bool {
558        self.filters.is_empty()
559    }
560
561    fn consume<E>(self) -> Result<Vec<<E as Extractor>::Output>, EnvelopeError>
562    where
563        for<'a> E: Default + Extractor + EnvelopeVisitor<'a>,
564        for<'a> EnvelopeError: From<<E as EnvelopeVisitor<'a>>::Error>,
565        Self: Sized,
566    {
567        self.filters.consume()
568    }
569
570    fn group_messages(
571        &self,
572    ) -> Result<Vec<Option<xmtp_proto::types::GroupMessage>>, EnvelopeError> {
573        self.filters.group_messages()
574    }
575
576    fn welcome_messages(
577        &self,
578    ) -> Result<Vec<Option<xmtp_proto::types::WelcomeMessage>>, EnvelopeError> {
579        self.filters.welcome_messages()
580    }
581
582    fn orphans(&self) -> Result<Vec<OrphanedEnvelope>, EnvelopeError> {
583        self.filters.orphans()
584    }
585}
586
587impl EnvelopeCollection<'_> for SubscribeWelcomeMessagesRequest {
588    fn topics(&self) -> Result<Vec<Topic>, EnvelopeError> {
589        self.filters.topics()
590    }
591
592    fn cursors(&self) -> Result<Vec<Cursor>, EnvelopeError> {
593        self.filters.cursors()
594    }
595
596    fn payloads(&self) -> Result<Vec<Payload>, EnvelopeError> {
597        self.filters.payloads()
598    }
599
600    fn sha256_hashes(&self) -> Result<Vec<Vec<u8>>, EnvelopeError> {
601        self.filters.sha256_hashes()
602    }
603
604    fn client_envelopes(&self) -> Result<Vec<ClientEnvelope>, EnvelopeError> {
605        self.filters.client_envelopes()
606    }
607
608    fn len(&self) -> usize {
609        self.filters.len()
610    }
611
612    fn is_empty(&self) -> bool {
613        self.filters.is_empty()
614    }
615
616    fn consume<E>(self) -> Result<Vec<<E as Extractor>::Output>, EnvelopeError>
617    where
618        for<'a> E: Default + Extractor + EnvelopeVisitor<'a>,
619        for<'a> EnvelopeError: From<<E as EnvelopeVisitor<'a>>::Error>,
620        Self: Sized,
621    {
622        self.filters.consume()
623    }
624
625    fn group_messages(
626        &self,
627    ) -> Result<Vec<Option<xmtp_proto::types::GroupMessage>>, EnvelopeError> {
628        self.filters.group_messages()
629    }
630
631    fn welcome_messages(
632        &self,
633    ) -> Result<Vec<Option<xmtp_proto::types::WelcomeMessage>>, EnvelopeError> {
634        self.filters.welcome_messages()
635    }
636
637    fn orphans(&self) -> Result<Vec<OrphanedEnvelope>, EnvelopeError> {
638        self.filters.orphans()
639    }
640}
641
642#[cfg(any(test, feature = "test-utils"))]
643impl<'env> ProtocolEnvelope<'env> for u32 {
644    type Nested<'a> = ();
645
646    fn accept<V: EnvelopeVisitor<'env>>(&self, visitor: &mut V) -> Result<(), EnvelopeError>
647    where
648        EnvelopeError: From<<V as EnvelopeVisitor<'env>>::Error>,
649    {
650        visitor.test_visit_u32(self)?;
651        Ok(())
652    }
653
654    fn get_nested(&self) -> Result<Self::Nested<'_>, xmtp_proto::ConversionError> {
655        Ok(())
656    }
657}
658
659#[cfg(test)]
660mod tests {
661    use super::*;
662    use crate::protocol::Envelope;
663    use crate::protocol::extractors::test_utils::*;
664    use rstest::rstest;
665    use xmtp_common::Generate;
666    use xmtp_cryptography::XmtpInstallationCredential;
667    use xmtp_proto::types::TopicKind;
668    use xmtp_proto::xmtp::mls::api::v1::{
669        GroupMessage as V3ProtoGroupMessage, WelcomeMessage as V3ProtoWelcomeMessage,
670        group_message, group_message_input::V1 as GroupMessageV1, welcome_message,
671        welcome_message_input::V1 as WelcomeMessageV1,
672    };
673    use xmtp_proto::xmtp::xmtpv4::envelopes::AuthenticatedData;
674
675    /// Minimal test visitor that tracks which methods were called
676    #[derive(Default, Debug)]
677    struct TestVisitor {
678        visited_originator: bool,
679        visited_client: bool,
680        visited_group_message_v1: bool,
681        visited_welcome_message_v1: bool,
682        visited_upload_key_package: bool,
683        visited_identity_update: bool,
684        visited_none: bool,
685        visited_v3_group_message: bool,
686        visited_v3_welcome_message: bool,
687    }
688
689    impl<'env> EnvelopeVisitor<'env> for TestVisitor {
690        type Error = super::EnvelopeError;
691
692        fn visit_originator(&mut self, _e: &OriginatorEnvelope) -> Result<(), Self::Error> {
693            self.visited_originator = true;
694            Ok(())
695        }
696
697        fn visit_client(&mut self, _e: &ClientEnvelope) -> Result<(), Self::Error> {
698            self.visited_client = true;
699            Ok(())
700        }
701
702        fn visit_group_message_v1(&mut self, _m: &GroupMessageV1) -> Result<(), Self::Error> {
703            self.visited_group_message_v1 = true;
704            Ok(())
705        }
706
707        fn visit_welcome_message_v1(&mut self, _m: &WelcomeMessageV1) -> Result<(), Self::Error> {
708            self.visited_welcome_message_v1 = true;
709            Ok(())
710        }
711
712        fn visit_upload_key_package(
713            &mut self,
714            _p: &UploadKeyPackageRequest,
715        ) -> Result<(), Self::Error> {
716            self.visited_upload_key_package = true;
717            Ok(())
718        }
719
720        fn visit_identity_update(&mut self, _u: &IdentityUpdate) -> Result<(), Self::Error> {
721            self.visited_identity_update = true;
722            Ok(())
723        }
724
725        fn visit_none(&mut self) -> Result<(), Self::Error> {
726            self.visited_none = true;
727            Ok(())
728        }
729
730        fn visit_v3_group_message(&mut self, _m: &group_message::V1) -> Result<(), Self::Error> {
731            self.visited_v3_group_message = true;
732            Ok(())
733        }
734
735        fn visit_v3_welcome_message(
736            &mut self,
737            _m: &welcome_message::V1,
738        ) -> Result<(), Self::Error> {
739            self.visited_v3_welcome_message = true;
740            Ok(())
741        }
742    }
743
744    #[rstest]
745    #[case::group_message(
746        |builder: TestEnvelopeBuilder| builder.with_application_message(vec![1,2,3]),
747        |visitor: &TestVisitor| visitor.visited_group_message_v1,
748    )]
749    #[case::welcome_message(
750        |builder: TestEnvelopeBuilder| builder.with_welcome_message(vec![1,2,3,4]),
751        |visitor: &TestVisitor| visitor.visited_welcome_message_v1,
752    )]
753    #[case::key_package(
754        |builder: TestEnvelopeBuilder| builder.with_key_package("test".to_string(), XmtpInstallationCredential::default()),
755        |visitor: &TestVisitor| visitor.visited_upload_key_package,
756    )]
757    #[case::identity_update(
758        |builder: TestEnvelopeBuilder| builder.with_identity_update(),
759        |visitor: &TestVisitor| visitor.visited_identity_update,
760    )]
761    #[xmtp_common::test]
762    async fn envelope_visitor_flows<F, P>(#[case] envelope_builder: F, #[case] payload_check: P)
763    where
764        F: Fn(TestEnvelopeBuilder) -> TestEnvelopeBuilder,
765        P: Fn(&TestVisitor) -> bool,
766    {
767        let envelope = envelope_builder(TestEnvelopeBuilder::new()).build();
768        let mut visitor = TestVisitor::default();
769        envelope.accept(&mut visitor).unwrap();
770
771        // All envelopes should visit these core types
772        assert!(visitor.visited_originator, "originator should be visited");
773        assert!(visitor.visited_client, "client should be visited");
774
775        // Payload-specific assertion
776        assert!(
777            payload_check(&visitor),
778            "payload-specific visitor should be called"
779        );
780
781        // Extraction should work
782        assert!(envelope.topic().is_ok(), "topic extraction should work");
783        assert!(envelope.payload().is_ok(), "payload extraction should work");
784        assert!(
785            envelope.client_envelope().is_ok(),
786            "client envelope extraction should work"
787        );
788    }
789
790    #[xmtp_common::test]
791    fn envelope_collections() {
792        let envelopes = vec![
793            TestEnvelopeBuilder::new()
794                .with_application_message(vec![1, 2, 3])
795                .build(),
796            TestEnvelopeBuilder::new()
797                .with_welcome_message(vec![4, 5, 6, 7])
798                .build(),
799            TestEnvelopeBuilder::new()
800                .with_key_package("test".to_string(), XmtpInstallationCredential::default())
801                .build(),
802            TestEnvelopeBuilder::new().with_identity_update().build(),
803        ];
804        // Test EnvelopeCollection implementations
805        let response = SubscribeEnvelopesResponse {
806            envelopes: envelopes.clone(),
807        };
808        assert_eq!(response.len(), 4);
809        assert_eq!(response.payloads().unwrap().len(), 4);
810        assert_eq!(response.client_envelopes().unwrap().len(), 4);
811        assert!(!response.is_empty());
812
813        let empty_response = SubscribeEnvelopesResponse { envelopes: vec![] };
814        assert_eq!(empty_response.len(), 0);
815        assert!(empty_response.is_empty());
816    }
817
818    #[xmtp_common::test]
819    fn envelope_error_handling() {
820        // Test corrupted originator envelope
821        let mut envelope = TestEnvelopeBuilder::new()
822            .with_application_message(vec![1, 2, 3])
823            .build();
824        envelope.unsigned_originator_envelope = vec![0xFF];
825        assert!(envelope.get_nested().is_err());
826
827        // Test corrupted payer envelope
828        let unsigned = UnsignedOriginatorEnvelope {
829            originator_node_id: 1,
830            originator_sequence_id: 1,
831            originator_ns: 1000,
832            payer_envelope_bytes: vec![0xFF, 0xFF, 0xFF],
833            base_fee_picodollars: 0,
834            congestion_fee_picodollars: 0,
835            expiry_unixtime: 0,
836        };
837        assert!(unsigned.get_nested().is_err());
838
839        // Test corrupted client envelope
840        let payer = PayerEnvelope {
841            unsigned_client_envelope: vec![0xFF, 0xFF, 0xFF],
842            payer_signature: None,
843            target_originator: 0,
844            message_retention_days: 30,
845        };
846        assert!(payer.get_nested().is_err());
847    }
848
849    #[xmtp_common::test]
850    fn envelope_edge_cases() {
851        // Test empty payload handling
852        let client = ClientEnvelope {
853            aad: Some(AuthenticatedData::with_topic(
854                TopicKind::IdentityUpdatesV1.create([0, 1, 2]),
855            )),
856            payload: None,
857        };
858        let mut visitor = TestVisitor::default();
859        client.accept(&mut visitor).unwrap();
860        assert!(visitor.visited_client && visitor.visited_none);
861
862        // Test Option<T> ProtocolEnvelope implementation
863        let envelope = TestEnvelopeBuilder::new()
864            .with_application_message(vec![1, 2, 3])
865            .build();
866        let some_envelope = Some(&envelope);
867        let none_envelope: Option<&OriginatorEnvelope> = None;
868
869        let mut visitor = TestVisitor::default();
870        some_envelope.accept(&mut visitor).unwrap();
871        assert!(visitor.visited_originator && !visitor.visited_none);
872
873        let mut visitor = TestVisitor::default();
874        none_envelope.accept(&mut visitor).unwrap();
875        assert!(visitor.visited_none && !visitor.visited_originator);
876    }
877
878    #[xmtp_common::test]
879    fn test_v3_message_visitors() {
880        macro_rules! test_case {
881            ($msg:expr, $expected:expr, $field:ident) => {{
882                let mut visitor = TestVisitor::default();
883                $msg.accept(&mut visitor).unwrap();
884                assert_eq!(
885                    visitor.$field,
886                    $expected,
887                    "V3 {} should be {}",
888                    stringify!($field),
889                    $expected
890                );
891            }};
892        }
893
894        // Test all V3 message visitor combinations
895        test_case!(
896            V3ProtoGroupMessage {
897                version: Some(group_message::Version::V1(group_message::V1::generate()))
898            },
899            true,
900            visited_v3_group_message
901        );
902        test_case!(
903            V3ProtoGroupMessage { version: None },
904            false,
905            visited_v3_group_message
906        );
907        test_case!(
908            V3ProtoWelcomeMessage {
909                version: Some(welcome_message::Version::V1(welcome_message::V1::generate()))
910            },
911            true,
912            visited_v3_welcome_message
913        );
914        test_case!(
915            V3ProtoWelcomeMessage { version: None },
916            false,
917            visited_v3_welcome_message
918        );
919        test_case!(
920            group_message::Version::V1(group_message::V1::generate()),
921            true,
922            visited_v3_group_message
923        );
924        test_case!(
925            welcome_message::Version::V1(welcome_message::V1::generate()),
926            true,
927            visited_v3_welcome_message
928        );
929    }
930}