encode.rs (3514B)
1 #[cfg(not(feature = "std"))] 2 use alloc::vec; 3 #[cfg(not(feature = "std"))] 4 use alloc::{ 5 format, 6 string::{String, ToString}, 7 vec::Vec, 8 }; 9 10 use radroots_events::kinds::KIND_MESSAGE_FILE; 11 use radroots_events::message_file::{RadrootsMessageFile, RadrootsMessageFileDimensions}; 12 13 use crate::error::EventEncodeError; 14 use crate::message::tags::{build_recipient_tags, build_reply_tag, build_subject_tag}; 15 use crate::wire::WireEventParts; 16 17 const DEFAULT_KIND: u32 = KIND_MESSAGE_FILE; 18 19 fn validate_required(value: &str, field: &'static str) -> Result<(), EventEncodeError> { 20 if value.trim().is_empty() { 21 return Err(EventEncodeError::EmptyRequiredField(field)); 22 } 23 Ok(()) 24 } 25 26 fn push_required_tag( 27 tags: &mut Vec<Vec<String>>, 28 key: &'static str, 29 value: &str, 30 field: &'static str, 31 ) -> Result<(), EventEncodeError> { 32 validate_required(value, field)?; 33 tags.push(vec![key.to_string(), value.to_string()]); 34 Ok(()) 35 } 36 37 fn push_optional_tag(tags: &mut Vec<Vec<String>>, key: &'static str, value: &Option<String>) { 38 if let Some(value) = value { 39 tags.push(vec![key.to_string(), value.clone()]); 40 } 41 } 42 43 fn push_dimensions_tag( 44 tags: &mut Vec<Vec<String>>, 45 dimensions: &Option<RadrootsMessageFileDimensions>, 46 ) { 47 if let Some(dimensions) = dimensions { 48 tags.push(vec![ 49 "dim".to_string(), 50 format!("{}x{}", dimensions.w, dimensions.h), 51 ]); 52 } 53 } 54 55 pub fn message_file_build_tags( 56 message: &RadrootsMessageFile, 57 ) -> Result<Vec<Vec<String>>, EventEncodeError> { 58 let mut tags = build_recipient_tags(&message.recipients)?; 59 if let Some(tag) = build_reply_tag(&message.reply_to)? { 60 tags.push(tag); 61 } 62 if let Some(tag) = build_subject_tag(&message.subject)? { 63 tags.push(tag); 64 } 65 66 push_required_tag(&mut tags, "file-type", &message.file_type, "file_type")?; 67 push_required_tag( 68 &mut tags, 69 "encryption-algorithm", 70 &message.encryption_algorithm, 71 "encryption_algorithm", 72 )?; 73 push_required_tag( 74 &mut tags, 75 "decryption-key", 76 &message.decryption_key, 77 "decryption_key", 78 )?; 79 push_required_tag( 80 &mut tags, 81 "decryption-nonce", 82 &message.decryption_nonce, 83 "decryption_nonce", 84 )?; 85 push_required_tag(&mut tags, "x", &message.encrypted_hash, "encrypted_hash")?; 86 87 push_optional_tag(&mut tags, "ox", &message.original_hash); 88 if let Some(size) = message.size { 89 tags.push(vec!["size".to_string(), size.to_string()]); 90 } 91 push_dimensions_tag(&mut tags, &message.dimensions); 92 push_optional_tag(&mut tags, "blurhash", &message.blurhash); 93 push_optional_tag(&mut tags, "thumb", &message.thumb); 94 for fallback in &message.fallbacks { 95 validate_required(fallback, "fallback")?; 96 tags.push(vec!["fallback".to_string(), fallback.clone()]); 97 } 98 99 Ok(tags) 100 } 101 102 pub fn to_wire_parts(message: &RadrootsMessageFile) -> Result<WireEventParts, EventEncodeError> { 103 validate_required(&message.file_url, "file_url")?; 104 let tags = message_file_build_tags(message)?; 105 Ok(WireEventParts { 106 kind: DEFAULT_KIND, 107 content: message.file_url.clone(), 108 tags, 109 }) 110 } 111 112 pub fn to_wire_parts_with_kind( 113 message: &RadrootsMessageFile, 114 kind: u32, 115 ) -> Result<WireEventParts, EventEncodeError> { 116 if kind != DEFAULT_KIND { 117 return Err(EventEncodeError::InvalidKind(kind)); 118 } 119 to_wire_parts(message) 120 }