xmtp_api_d14n/protocol/extractors/
cursor.rs

1//! Extractor for a envelope [`Cursor`](xmtp_proto::types::Cursor)
2//! useful for verifying a message has been read or maybe duplicates.
3use xmtp_proto::ConversionError;
4use xmtp_proto::mls_v1::welcome_message::WelcomePointer as V3WelcomePointer;
5use xmtp_proto::types::Cursor;
6use xmtp_proto::xmtp::mls::api::v1::{
7    group_message::V1 as V3GroupMessage, welcome_message::V1 as V3WelcomeMessage,
8};
9use xmtp_proto::xmtp::xmtpv4::envelopes::UnsignedOriginatorEnvelope;
10
11use crate::protocol::{EnvelopeVisitor, Extractor};
12
13/// Extract Cursor from Envelopes
14#[derive(Default, Clone, Debug)]
15pub struct CursorExtractor {
16    cursor: Option<Cursor>,
17}
18
19impl CursorExtractor {
20    pub fn new() -> Self {
21        Default::default()
22    }
23}
24
25impl Extractor for CursorExtractor {
26    type Output = Result<Cursor, ConversionError>;
27
28    fn get(self) -> Self::Output {
29        self.cursor.ok_or(ConversionError::Missing {
30            item: "cursor",
31            r#type: std::any::type_name::<Cursor>(),
32        })
33    }
34}
35
36impl EnvelopeVisitor<'_> for CursorExtractor {
37    type Error = ConversionError;
38
39    fn visit_unsigned_originator(
40        &mut self,
41        e: &UnsignedOriginatorEnvelope,
42    ) -> Result<(), Self::Error> {
43        self.cursor = Some(Cursor::new(e.originator_sequence_id, e.originator_node_id));
44        Ok(())
45    }
46
47    fn visit_v3_group_message(&mut self, m: &V3GroupMessage) -> Result<(), Self::Error> {
48        self.cursor = Some(Cursor::v3_messages(m.id));
49        Ok(())
50    }
51
52    fn visit_v3_welcome_message(&mut self, m: &V3WelcomeMessage) -> Result<(), Self::Error> {
53        self.cursor = Some(Cursor::v3_welcomes(m.id));
54        Ok(())
55    }
56
57    fn visit_v3_welcome_pointer(&mut self, m: &V3WelcomePointer) -> Result<(), Self::Error> {
58        self.cursor = Some(Cursor::v3_welcomes(m.id));
59        Ok(())
60    }
61}