CommonLibrary/Transport/
UnifiedRequest.rs1#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
2use std::collections::HashMap;
7
8use serde::{Deserialize, Serialize};
9
10use super::Common::{
11 CorrelationId,
12 CorrelationIdGenerator,
13 SystemTimestampGenerator,
14 Timestamp,
15 TimestampGenerator,
16 TransportType,
17 UuidCorrelationIdGenerator,
18};
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub struct UnifiedRequest {
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub CorrelationIdentifier:Option<CorrelationId>,
26
27 pub Method:String,
29
30 pub Payload:Vec<u8>,
32
33 #[serde(skip_serializing_if = "HashMap::is_empty")]
35 pub Metadata:HashMap<String, String>,
36
37 pub CreatedAt:Timestamp,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub TransportHint:Option<TransportType>,
43}
44
45impl UnifiedRequest {
46 pub fn New(Method:impl Into<String>) -> Self {
48 Self {
49 CorrelationIdentifier:Some(UuidCorrelationIdGenerator::Generate()),
50
51 Method:Method.into(),
52
53 Payload:Vec::new(),
54
55 Metadata:HashMap::new(),
56
57 CreatedAt:SystemTimestampGenerator::Now(),
58
59 TransportHint:None,
60 }
61 }
62
63 pub fn WithCorrelationIdentifier(mut self, CorrelationIdentifier:CorrelationId) -> Self {
65 self.CorrelationIdentifier = Some(CorrelationIdentifier);
66
67 self
68 }
69
70 pub fn WithPayload(mut self, Payload:Vec<u8>) -> Self {
72 self.Payload = Payload;
73
74 self
75 }
76
77 pub fn WithMetadata(mut self, Key:impl Into<String>, Value:impl Into<String>) -> Self {
79 self.Metadata.insert(Key.into(), Value.into());
80
81 self
82 }
83
84 pub fn WithMetadataMap(mut self, Metadata:HashMap<String, String>) -> Self {
86 self.Metadata = Metadata;
87
88 self
89 }
90
91 pub fn WithTimeout(mut self, TimeoutMilliseconds:u64) -> Self {
93 self.Metadata.insert("timeout_ms".to_string(), TimeoutMilliseconds.to_string());
94
95 self
96 }
97
98 pub fn WithPriority(mut self, Priority:u32) -> Self {
100 self.Metadata.insert("priority".to_string(), Priority.to_string());
101
102 self
103 }
104
105 pub fn WithTransportHint(mut self, TransportKind:TransportType) -> Self {
107 self.TransportHint = Some(TransportKind);
108
109 self
110 }
111
112 pub fn TimeoutMilliseconds(&self) -> Option<u64> {
114 self.Metadata.get("timeout_ms").and_then(|Value| Value.parse().ok())
115 }
116
117 pub fn Priority(&self) -> Option<u32> { self.Metadata.get("priority").and_then(|Value| Value.parse().ok()) }
119
120 pub fn Validate(&self) -> Result<(), String> {
122 if self.Method.is_empty() {
123 return Err("method cannot be empty".to_string());
124 }
125
126 if let Some(Identifier) = &self.CorrelationIdentifier {
127 if Identifier.is_empty() {
128 return Err("correlation_id cannot be empty if specified".to_string());
129 }
130 }
131
132 Ok(())
133 }
134}
135
136#[cfg(test)]
137mod tests {
138
139 use super::*;
140
141 #[test]
142 fn TestUnifiedRequestCreation() {
143 let Request = UnifiedRequest::New("test.method");
144
145 assert!(!Request.Method.is_empty());
146
147 assert!(Request.CorrelationIdentifier.is_some());
148
149 assert_eq!(Request.Payload, Vec::<u8>::new());
150
151 assert!(Request.Metadata.is_empty());
152
153 assert!(Request.TransportHint.is_none());
154 }
155
156 #[test]
157 fn TestUnifiedRequestBuilder() {
158 let Request = UnifiedRequest::New("fileSystem.readFile")
159 .WithPayload(b"{\"path\": \"/tmp/test.txt\"}".to_vec())
160 .WithTimeout(5000)
161 .WithPriority(10)
162 .WithMetadata("traceparent", "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01")
163 .WithTransportHint(TransportType::Grpc);
164
165 assert_eq!(Request.Method, "fileSystem.readFile");
166
167 assert_eq!(Request.Payload, b"{\"path\": \"/tmp/test.txt\"}");
168
169 assert_eq!(Request.TimeoutMilliseconds(), Some(5000));
170
171 assert_eq!(Request.Priority(), Some(10));
172
173 assert_eq!(Request.TransportHint, Some(TransportType::Grpc));
174
175 assert!(Request.Metadata.contains_key("traceparent"));
176 }
177
178 #[test]
179 fn TestUnifiedRequestValidation() {
180 let mut Request = UnifiedRequest::New("valid.method");
181
182 assert!(Request.Validate().is_ok());
183
184 Request.Method = String::new();
185
186 assert!(Request.Validate().is_err());
187
188 Request.Method = "valid.method".to_string();
189
190 Request.CorrelationIdentifier = Some("".to_string());
191
192 assert!(Request.Validate().is_err());
193 }
194}