aleph_types/message/
pending.rs1use crate::chain::{Address, Chain, Signature};
2use crate::channel::Channel;
3use crate::item_hash::ItemHash;
4use crate::message::item_type::ItemType;
5use crate::message::{ContentSource, Message, MessageType};
6use crate::timestamp::Timestamp;
7use serde::ser::SerializeStruct;
8use serde::{Serialize, Serializer};
9use thiserror::Error;
10
11#[derive(Debug, Clone)]
17pub struct PendingMessage {
18 pub chain: Chain,
19 pub sender: Address,
20 pub signature: Signature,
21 pub message_type: MessageType,
22 pub item_type: ItemType,
23 pub item_content: String,
24 pub item_hash: ItemHash,
25 pub time: Timestamp,
26 pub channel: Option<Channel>,
27}
28
29impl Serialize for PendingMessage {
30 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
31 let has_content = self.item_type == ItemType::Inline;
32 let has_channel = self.channel.is_some();
33 let field_count = 7 + has_content as usize + has_channel as usize;
34
35 let mut state = serializer.serialize_struct("PendingMessage", field_count)?;
36 state.serialize_field("sender", &self.sender)?;
37 state.serialize_field("chain", &self.chain)?;
38 state.serialize_field("signature", &self.signature)?;
39 state.serialize_field("type", &self.message_type)?;
40 state.serialize_field("item_type", &self.item_type)?;
41 if has_content {
42 state.serialize_field("item_content", &self.item_content)?;
43 }
44 state.serialize_field("item_hash", &self.item_hash)?;
45 state.serialize_field("time", &self.time)?;
46 if let Some(channel) = &self.channel {
47 state.serialize_field("channel", channel)?;
48 }
49 state.end()
50 }
51}
52
53#[derive(Error, Debug)]
55pub enum PendingConversionError {
56 #[error("message has no signature; cannot be re-posted")]
59 MissingSignature,
60}
61
62impl TryFrom<&Message> for PendingMessage {
63 type Error = PendingConversionError;
64
65 fn try_from(message: &Message) -> Result<Self, Self::Error> {
66 let signature = message
67 .signature
68 .clone()
69 .ok_or(PendingConversionError::MissingSignature)?;
70 let (item_type, item_content) = match &message.content_source {
71 ContentSource::Inline { item_content } => (ItemType::Inline, item_content.clone()),
72 ContentSource::Storage => (ItemType::Storage, String::new()),
73 ContentSource::Ipfs => (ItemType::Ipfs, String::new()),
74 };
75 Ok(PendingMessage {
76 chain: message.chain.clone(),
77 sender: message.sender.clone(),
78 signature,
79 message_type: message.message_type,
80 item_type,
81 item_content,
82 item_hash: message.item_hash.clone(),
83 time: message.time.clone(),
84 channel: message.channel.clone(),
85 })
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use crate::{address, item_hash};
93
94 fn make_pending(item_type: ItemType) -> PendingMessage {
95 PendingMessage {
96 chain: Chain::Ethereum,
97 sender: address!("0xABCD"),
98 signature: Signature::from("0xSIG".to_string()),
99 message_type: MessageType::Post,
100 item_type,
101 item_content: r#"{"type":"test","address":"0xABCD","time":1234.0}"#.to_string(),
102 item_hash: item_hash!(
103 "d281eb8a69ba1f4dda2d71aaf3ded06caa92edd690ef3d0632f41aa91167762c"
104 ),
105 time: Timestamp::from(1234.0),
106 channel: None,
107 }
108 }
109
110 #[test]
111 fn test_pending_message_inline_includes_item_content() {
112 let msg = make_pending(ItemType::Inline);
113 let json = serde_json::to_value(&msg).unwrap();
114 assert_eq!(json["item_type"], "inline");
115 assert!(json.get("item_content").is_some());
116 assert_eq!(json["item_content"], msg.item_content);
117 }
118
119 #[test]
120 fn test_pending_message_storage_omits_item_content() {
121 let msg = make_pending(ItemType::Storage);
122 let json = serde_json::to_value(&msg).unwrap();
123 assert_eq!(json["item_type"], "storage");
124 assert!(json.get("item_content").is_none());
125 }
126
127 #[test]
128 fn test_pending_message_ipfs_omits_item_content() {
129 let msg = make_pending(ItemType::Ipfs);
130 let json = serde_json::to_value(&msg).unwrap();
131 assert_eq!(json["item_type"], "ipfs");
132 assert!(json.get("item_content").is_none());
133 }
134}