tap_msg/message/basic_message/
mod.rs1use crate::error::{Error, Result};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use tap_msg_derive::TapMessage;
13
14pub const BASIC_MESSAGE_TYPE: &str = "https://didcomm.org/basicmessage/2.0/message";
15
16#[derive(Debug, Clone, Serialize, Deserialize, TapMessage)]
22#[tap(
23 message_type = "https://didcomm.org/basicmessage/2.0/message",
24 custom_validation
25)]
26pub struct BasicMessage {
27 pub content: String,
29
30 #[serde(skip_serializing_if = "Option::is_none")]
32 pub locale: Option<String>,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub sent_time: Option<u64>,
37
38 #[serde(flatten)]
40 pub metadata: HashMap<String, serde_json::Value>,
41}
42
43impl BasicMessage {
44 pub fn new(content: String) -> Self {
46 Self {
47 content,
48 locale: None,
49 sent_time: Some(chrono::Utc::now().timestamp_millis() as u64),
50 metadata: HashMap::new(),
51 }
52 }
53
54 pub fn with_locale(content: String, locale: String) -> Self {
56 Self {
57 content,
58 locale: Some(locale),
59 sent_time: Some(chrono::Utc::now().timestamp_millis() as u64),
60 metadata: HashMap::new(),
61 }
62 }
63
64 pub fn sent_time(mut self, timestamp: u64) -> Self {
66 self.sent_time = Some(timestamp);
67 self
68 }
69
70 pub fn with_metadata(mut self, key: String, value: serde_json::Value) -> Self {
72 self.metadata.insert(key, value);
73 self
74 }
75
76 pub fn get_content(&self) -> &str {
78 &self.content
79 }
80
81 pub fn get_locale(&self) -> Option<&str> {
83 self.locale.as_deref()
84 }
85
86 pub fn get_sent_time(&self) -> Option<u64> {
88 self.sent_time
89 }
90}
91
92impl BasicMessage {
93 pub fn validate_basicmessage(&self) -> Result<()> {
95 if self.content.is_empty() {
96 return Err(Error::Validation(
97 "Basic message content cannot be empty".to_string(),
98 ));
99 }
100
101 if self.content.len() > 10000 {
103 return Err(Error::Validation(
104 "Basic message content exceeds maximum length of 10000 characters".to_string(),
105 ));
106 }
107
108 Ok(())
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn test_basic_message_creation() {
118 let message = BasicMessage::new("Hello, world!".to_string());
119 assert_eq!(message.content, "Hello, world!");
120 assert!(message.locale.is_none());
121 assert!(message.sent_time.is_some());
122 assert!(message.metadata.is_empty());
123 }
124
125 #[test]
126 fn test_basic_message_with_locale() {
127 let message = BasicMessage::with_locale("Hola, mundo!".to_string(), "es".to_string());
128 assert_eq!(message.content, "Hola, mundo!");
129 assert_eq!(message.locale, Some("es".to_string()));
130 assert!(message.sent_time.is_some());
131 }
132
133 #[test]
134 fn test_basic_message_with_metadata() {
135 let message = BasicMessage::new("Test message".to_string())
136 .with_metadata("priority".to_string(), serde_json::json!("high"))
137 .with_metadata("category".to_string(), serde_json::json!("alert"));
138
139 assert_eq!(message.metadata.len(), 2);
140 assert_eq!(
141 message.metadata.get("priority"),
142 Some(&serde_json::json!("high"))
143 );
144 assert_eq!(
145 message.metadata.get("category"),
146 Some(&serde_json::json!("alert"))
147 );
148 }
149
150 #[test]
151 fn test_basic_message_getters() {
152 let timestamp = chrono::Utc::now().timestamp_millis() as u64;
153 let message = BasicMessage::new("Test".to_string()).sent_time(timestamp);
154
155 assert_eq!(message.get_content(), "Test");
156 assert_eq!(message.get_locale(), None);
157 assert_eq!(message.get_sent_time(), Some(timestamp));
158 }
159
160 #[test]
161 fn test_basic_message_serialization() {
162 let message = BasicMessage::with_locale("Test message".to_string(), "en".to_string())
163 .with_metadata("test_key".to_string(), serde_json::json!("test_value"));
164
165 let serialized = serde_json::to_string(&message).unwrap();
166 let deserialized: BasicMessage = serde_json::from_str(&serialized).unwrap();
167
168 assert_eq!(message.content, deserialized.content);
169 assert_eq!(message.locale, deserialized.locale);
170 assert_eq!(message.sent_time, deserialized.sent_time);
171 assert_eq!(message.metadata, deserialized.metadata);
172 }
173
174 #[test]
175 fn test_basic_message_validation() {
176 let message = BasicMessage::new("Test".to_string());
177 assert!(message.validate_basicmessage().is_ok());
178
179 let empty_message = BasicMessage {
180 content: "".to_string(),
181 locale: None,
182 sent_time: None,
183 metadata: HashMap::new(),
184 };
185 assert!(empty_message.validate_basicmessage().is_err());
186
187 let long_message = BasicMessage::new("a".repeat(10001));
188 assert!(long_message.validate_basicmessage().is_err());
189 }
190
191 #[test]
192 fn test_message_type() {
193 use crate::message::tap_message_trait::TapMessageBody;
194 assert_eq!(BasicMessage::message_type(), BASIC_MESSAGE_TYPE);
195 }
196}