tap_msg/message/trust_ping/
mod.rs1use crate::error::{Error, Result};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use tap_msg_derive::TapMessage;
13
14pub const TRUST_PING_TYPE: &str = "https://didcomm.org/trust-ping/2.0/ping";
15pub const TRUST_PING_RESPONSE_TYPE: &str = "https://didcomm.org/trust-ping/2.0/ping-response";
16
17#[derive(Debug, Clone, Serialize, Deserialize, TapMessage)]
22#[tap(
23 message_type = "https://didcomm.org/trust-ping/2.0/ping",
24 custom_validation
25)]
26pub struct TrustPing {
27 #[serde(default = "default_response_requested")]
29 pub response_requested: bool,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub comment: Option<String>,
34
35 #[serde(flatten)]
37 pub metadata: HashMap<String, serde_json::Value>,
38}
39
40#[derive(Debug, Clone, Default, Serialize, Deserialize, TapMessage)]
45#[tap(
46 message_type = "https://didcomm.org/trust-ping/2.0/ping-response",
47 custom_validation
48)]
49pub struct TrustPingResponse {
50 #[serde(skip_serializing_if = "Option::is_none")]
52 pub comment: Option<String>,
53
54 #[serde(default)]
56 pub thread_id: String,
57
58 #[serde(flatten, default)]
60 pub metadata: HashMap<String, serde_json::Value>,
61}
62
63fn default_response_requested() -> bool {
64 true
65}
66
67impl Default for TrustPing {
68 fn default() -> Self {
69 Self {
70 response_requested: true,
71 comment: None,
72 metadata: HashMap::new(),
73 }
74 }
75}
76
77impl TrustPing {
78 pub fn new() -> Self {
80 Self::default()
81 }
82
83 pub fn with_comment(comment: String) -> Self {
85 Self {
86 comment: Some(comment),
87 response_requested: true,
88 metadata: HashMap::new(),
89 }
90 }
91
92 pub fn response_requested(mut self, requested: bool) -> Self {
94 self.response_requested = requested;
95 self
96 }
97
98 pub fn with_metadata(mut self, key: String, value: serde_json::Value) -> Self {
100 self.metadata.insert(key, value);
101 self
102 }
103
104 pub fn validate_trustping(&self) -> Result<()> {
106 if let Some(ref comment) = self.comment {
109 if comment.len() > 1000 {
110 return Err(Error::Validation(
111 "Trust Ping comment exceeds maximum length of 1000 characters".to_string(),
112 ));
113 }
114 }
115
116 Ok(())
117 }
118}
119
120impl TrustPingResponse {
121 pub fn new(thread_id: String) -> Self {
123 Self {
124 comment: None,
125 thread_id,
126 metadata: HashMap::new(),
127 }
128 }
129
130 pub fn with_comment(thread_id: String, comment: String) -> Self {
132 Self {
133 comment: Some(comment),
134 thread_id,
135 metadata: HashMap::new(),
136 }
137 }
138
139 pub fn with_metadata(mut self, key: String, value: serde_json::Value) -> Self {
141 self.metadata.insert(key, value);
142 self
143 }
144
145 pub fn validate_trustpingresponse(&self) -> Result<()> {
147 if self.thread_id.is_empty() {
148 return Err(Error::Validation(
149 "Thread ID is required in Trust Ping Response".to_string(),
150 ));
151 }
152
153 if let Some(ref comment) = self.comment {
155 if comment.len() > 1000 {
156 return Err(Error::Validation(
157 "Trust Ping Response comment exceeds maximum length of 1000 characters"
158 .to_string(),
159 ));
160 }
161 }
162
163 Ok(())
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_trust_ping_creation() {
173 let ping = TrustPing::new();
174 assert!(ping.response_requested);
175 assert!(ping.comment.is_none());
176 assert!(ping.metadata.is_empty());
177 }
178
179 #[test]
180 fn test_trust_ping_with_comment() {
181 let ping = TrustPing::with_comment("Testing connectivity".to_string());
182 assert_eq!(ping.comment, Some("Testing connectivity".to_string()));
183 assert!(ping.response_requested);
184 }
185
186 #[test]
187 fn test_trust_ping_no_response() {
188 let ping = TrustPing::new().response_requested(false);
189 assert!(!ping.response_requested);
190 }
191
192 #[test]
193 fn test_trust_ping_response_creation() {
194 let response = TrustPingResponse::new("thread-123".to_string());
195 assert_eq!(response.thread_id, "thread-123");
196 assert!(response.comment.is_none());
197 assert!(response.metadata.is_empty());
198 }
199
200 #[test]
201 fn test_trust_ping_response_with_comment() {
202 let response =
203 TrustPingResponse::with_comment("thread-123".to_string(), "Pong!".to_string());
204 assert_eq!(response.thread_id, "thread-123");
205 assert_eq!(response.comment, Some("Pong!".to_string()));
206 }
207
208 #[test]
209 fn test_trust_ping_validation() {
210 let ping = TrustPing::new();
211 assert!(ping.validate_trustping().is_ok());
212
213 let long_comment = "a".repeat(1001);
214 let ping_with_long_comment = TrustPing::with_comment(long_comment);
215 assert!(ping_with_long_comment.validate_trustping().is_err());
216 }
217
218 #[test]
219 fn test_trust_ping_response_validation() {
220 let response = TrustPingResponse::new("valid-thread-id".to_string());
221 assert!(response.validate_trustpingresponse().is_ok());
222
223 let response_empty_thread = TrustPingResponse::new("".to_string());
224 assert!(response_empty_thread.validate_trustpingresponse().is_err());
225
226 let long_comment = "a".repeat(1001);
227 let response_with_long_comment =
228 TrustPingResponse::with_comment("valid-thread-id".to_string(), long_comment);
229 assert!(response_with_long_comment
230 .validate_trustpingresponse()
231 .is_err());
232 }
233
234 #[test]
235 fn test_trust_ping_serialization() {
236 let ping = TrustPing::with_comment("Test".to_string())
237 .response_requested(false)
238 .with_metadata("test_key".to_string(), serde_json::json!("test_value"));
239
240 let serialized = serde_json::to_string(&ping).unwrap();
241 let deserialized: TrustPing = serde_json::from_str(&serialized).unwrap();
242
243 assert_eq!(ping.comment, deserialized.comment);
244 assert_eq!(ping.response_requested, deserialized.response_requested);
245 assert_eq!(ping.metadata, deserialized.metadata);
246 }
247
248 #[test]
249 fn test_trust_ping_response_serialization() {
250 let response =
251 TrustPingResponse::with_comment("thread-123".to_string(), "Pong!".to_string())
252 .with_metadata("test_key".to_string(), serde_json::json!("test_value"));
253
254 let serialized = serde_json::to_string(&response).unwrap();
255 let deserialized: TrustPingResponse = serde_json::from_str(&serialized).unwrap();
256
257 assert_eq!(response.comment, deserialized.comment);
258 assert_eq!(response.thread_id, deserialized.thread_id);
259 assert_eq!(response.metadata, deserialized.metadata);
260 }
261
262 #[test]
263 fn test_message_types() {
264 use crate::message::tap_message_trait::TapMessageBody;
265 assert_eq!(TrustPing::message_type(), TRUST_PING_TYPE);
266 assert_eq!(TrustPingResponse::message_type(), TRUST_PING_RESPONSE_TYPE);
267 }
268}