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