xmtp_content_types/
multi_remote_attachment.rs1use std::collections::HashMap;
2
3use crate::{CodecError, ContentCodec};
4use prost::Message;
5use xmtp_proto::xmtp::mls::message_contents::{
6 ContentTypeId, EncodedContent, content_types::MultiRemoteAttachment,
7};
8
9pub struct MultiRemoteAttachmentCodec {}
10
11impl MultiRemoteAttachmentCodec {
12 const AUTHORITY_ID: &'static str = "xmtp.org";
13 pub const TYPE_ID: &'static str = "multiRemoteStaticAttachment";
14 pub const MAJOR_VERSION: u32 = 1;
15 pub const MINOR_VERSION: u32 = 0;
16}
17
18impl MultiRemoteAttachmentCodec {
19 fn fallback(_: &MultiRemoteAttachment) -> Option<String> {
20 Some(
21 "Can't display this content. This app doesn't support multiple remote attachments."
22 .to_string(),
23 )
24 }
25}
26
27impl ContentCodec<MultiRemoteAttachment> for MultiRemoteAttachmentCodec {
28 fn content_type() -> ContentTypeId {
29 ContentTypeId {
30 authority_id: MultiRemoteAttachmentCodec::AUTHORITY_ID.to_string(),
31 type_id: MultiRemoteAttachmentCodec::TYPE_ID.to_string(),
32 version_major: MultiRemoteAttachmentCodec::MAJOR_VERSION,
33 version_minor: MultiRemoteAttachmentCodec::MINOR_VERSION,
34 }
35 }
36
37 fn encode(data: MultiRemoteAttachment) -> Result<EncodedContent, CodecError> {
38 let mut buf = Vec::new();
39 data.encode(&mut buf)
40 .map_err(|e| CodecError::Encode(e.to_string()))?;
41
42 Ok(EncodedContent {
43 r#type: Some(MultiRemoteAttachmentCodec::content_type()),
44 parameters: HashMap::new(),
45 fallback: Self::fallback(&data),
46 compression: None,
47 content: buf,
48 })
49 }
50
51 fn decode(content: EncodedContent) -> Result<MultiRemoteAttachment, CodecError> {
52 let decoded = MultiRemoteAttachment::decode(content.content.as_slice())
53 .map_err(|e| CodecError::Decode(e.to_string()))?;
54
55 Ok(decoded)
56 }
57
58 fn should_push() -> bool {
59 true
60 }
61}
62
63#[cfg(test)]
64pub(crate) mod tests {
65 use xmtp_proto::xmtp::mls::message_contents::content_types::RemoteAttachmentInfo;
66
67 use super::*;
68
69 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
70 #[cfg_attr(not(target_arch = "wasm32"), test)]
71 fn test_encode_decode() {
72 let attachment_info_1 = RemoteAttachmentInfo {
73 content_digest: "0123456789abcdef".to_string(),
74 secret: vec![0; 32],
75 nonce: vec![0; 16],
76 salt: vec![0; 16],
77 scheme: "https".to_string(),
78 url: "https://example.com/attachment".to_string(),
79 content_length: Some(1000),
80 filename: Some("attachment_1.jpg".to_string()),
81 };
82 let attachment_info_2 = RemoteAttachmentInfo {
83 content_digest: "0123456789abcdef".to_string(),
84 secret: vec![0; 32],
85 nonce: vec![0; 16],
86 salt: vec![0; 16],
87 scheme: "https".to_string(),
88 url: "https://example.com/attachment".to_string(),
89 content_length: Some(1000),
90 filename: Some("attachment_2.jpg".to_string()),
91 };
92
93 let filename_1 = attachment_info_1.filename.clone();
95 let filename_2 = attachment_info_2.filename.clone();
96
97 let new_multi_remote_attachment_data: MultiRemoteAttachment = MultiRemoteAttachment {
98 attachments: vec![attachment_info_1.clone(), attachment_info_2.clone()],
99 };
100
101 let encoded = MultiRemoteAttachmentCodec::encode(new_multi_remote_attachment_data).unwrap();
102 assert_eq!(
103 encoded.clone().r#type.unwrap().type_id,
104 "multiRemoteStaticAttachment"
105 );
106 assert!(!encoded.content.is_empty());
107
108 let decoded = MultiRemoteAttachmentCodec::decode(encoded).unwrap();
109 assert_eq!(decoded.attachments[0].filename, filename_1);
110 assert_eq!(decoded.attachments[1].filename, filename_2);
111 assert_eq!(decoded.attachments[0].content_length, Some(1000));
112 assert_eq!(decoded.attachments[1].content_length, Some(1000));
113 }
114}