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 Method:Method.into(),
51 Payload:Vec::new(),
52 Metadata:HashMap::new(),
53 CreatedAt:SystemTimestampGenerator::Now(),
54 TransportHint:None,
55 }
56 }
57
58 pub fn WithCorrelationIdentifier(mut self, CorrelationIdentifier:CorrelationId) -> Self {
60 self.CorrelationIdentifier = Some(CorrelationIdentifier);
61 self
62 }
63
64 pub fn WithPayload(mut self, Payload:Vec<u8>) -> Self {
66 self.Payload = Payload;
67 self
68 }
69
70 pub fn WithMetadata(mut self, Key:impl Into<String>, Value:impl Into<String>) -> Self {
72 self.Metadata.insert(Key.into(), Value.into());
73 self
74 }
75
76 pub fn WithMetadataMap(mut self, Metadata:HashMap<String, String>) -> Self {
78 self.Metadata = Metadata;
79 self
80 }
81
82 pub fn WithTimeout(mut self, TimeoutMilliseconds:u64) -> Self {
84 self.Metadata.insert("timeout_ms".to_string(), TimeoutMilliseconds.to_string());
85 self
86 }
87
88 pub fn WithPriority(mut self, Priority:u32) -> Self {
90 self.Metadata.insert("priority".to_string(), Priority.to_string());
91 self
92 }
93
94 pub fn WithTransportHint(mut self, TransportKind:TransportType) -> Self {
96 self.TransportHint = Some(TransportKind);
97 self
98 }
99
100 pub fn TimeoutMilliseconds(&self) -> Option<u64> {
102 self.Metadata.get("timeout_ms").and_then(|Value| Value.parse().ok())
103 }
104
105 pub fn Priority(&self) -> Option<u32> { self.Metadata.get("priority").and_then(|Value| Value.parse().ok()) }
107
108 pub fn Validate(&self) -> Result<(), String> {
110 if self.Method.is_empty() {
111 return Err("method cannot be empty".to_string());
112 }
113
114 if let Some(Identifier) = &self.CorrelationIdentifier {
115 if Identifier.is_empty() {
116 return Err("correlation_id cannot be empty if specified".to_string());
117 }
118 }
119
120 Ok(())
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn TestUnifiedRequestCreation() {
130 let Request = UnifiedRequest::New("test.method");
131 assert!(!Request.Method.is_empty());
132 assert!(Request.CorrelationIdentifier.is_some());
133 assert_eq!(Request.Payload, Vec::<u8>::new());
134 assert!(Request.Metadata.is_empty());
135 assert!(Request.TransportHint.is_none());
136 }
137
138 #[test]
139 fn TestUnifiedRequestBuilder() {
140 let Request = UnifiedRequest::New("fileSystem.readFile")
141 .WithPayload(b"{\"path\": \"/tmp/test.txt\"}".to_vec())
142 .WithTimeout(5000)
143 .WithPriority(10)
144 .WithMetadata("traceparent", "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01")
145 .WithTransportHint(TransportType::Grpc);
146
147 assert_eq!(Request.Method, "fileSystem.readFile");
148 assert_eq!(Request.Payload, b"{\"path\": \"/tmp/test.txt\"}");
149 assert_eq!(Request.TimeoutMilliseconds(), Some(5000));
150 assert_eq!(Request.Priority(), Some(10));
151 assert_eq!(Request.TransportHint, Some(TransportType::Grpc));
152 assert!(Request.Metadata.contains_key("traceparent"));
153 }
154
155 #[test]
156 fn TestUnifiedRequestValidation() {
157 let mut Request = UnifiedRequest::New("valid.method");
158 assert!(Request.Validate().is_ok());
159
160 Request.Method = String::new();
161 assert!(Request.Validate().is_err());
162
163 Request.Method = "valid.method".to_string();
164 Request.CorrelationIdentifier = Some("".to_string());
165 assert!(Request.Validate().is_err());
166 }
167}