dynamo_runtime/
protocols.rs1use serde::{Deserialize, Serialize};
17use std::str::FromStr;
18
19use crate::pipeline::PipelineError;
20
21pub mod annotated;
22
23pub type LeaseId = i64;
24
25const DEFAULT_NAMESPACE: &str = "NS";
27
28const DEFAULT_COMPONENT: &str = "C";
29
30const DEFAULT_ENDPOINT: &str = "E";
31
32#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
33pub struct Component {
34 pub name: String,
35 pub namespace: String,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
49pub struct Endpoint {
50 pub namespace: String,
51 pub component: String,
52 pub name: String,
53}
54
55impl PartialEq<Vec<&str>> for Endpoint {
56 fn eq(&self, other: &Vec<&str>) -> bool {
57 if other.len() != 3 {
58 return false;
59 }
60
61 self.namespace == other[0] && self.component == other[1] && self.name == other[2]
62 }
63}
64
65impl PartialEq<Endpoint> for Vec<&str> {
66 fn eq(&self, other: &Endpoint) -> bool {
67 other == self
68 }
69}
70
71impl Default for Endpoint {
72 fn default() -> Self {
73 Endpoint {
74 namespace: DEFAULT_NAMESPACE.to_string(),
75 component: DEFAULT_COMPONENT.to_string(),
76 name: DEFAULT_ENDPOINT.to_string(),
77 }
78 }
79}
80
81impl From<&str> for Endpoint {
82 fn from(input: &str) -> Self {
108 let mut result = Endpoint::default();
109
110 let elements: Vec<&str> = input
112 .trim_matches([' ', '/', '.'])
113 .split(['.', '/'])
114 .filter(|x| !x.is_empty())
115 .collect();
116
117 match elements.len() {
118 0 => {}
119 1 => {
120 result.component = elements[0].to_string();
121 }
122 2 => {
123 result.namespace = elements[0].to_string();
124 result.component = elements[1].to_string();
125 }
126 3 => {
127 result.namespace = elements[0].to_string();
128 result.component = elements[1].to_string();
129 result.name = elements[2].to_string();
130 }
131 x if x > 3 => {
132 result.namespace = elements[0].to_string();
133 result.component = elements[1].to_string();
134 result.name = elements[2..].join("_");
135 }
136 _ => unreachable!(),
137 }
138 result
139 }
140}
141
142impl FromStr for Endpoint {
143 type Err = PipelineError;
144
145 fn from_str(s: &str) -> Result<Self, Self::Err> {
163 Ok(Endpoint::from(s))
164 }
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
168#[serde(rename_all = "snake_case")]
169pub enum RouterType {
170 PushRoundRobin,
171 PushRandom,
172}
173
174impl Default for RouterType {
175 fn default() -> Self {
176 Self::PushRandom
177 }
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
181pub struct ModelMetaData {
182 pub name: String,
183 pub component: Component,
184 pub router_type: RouterType,
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use std::convert::TryFrom;
191 use std::str::FromStr;
192
193 #[test]
194 fn test_router_type_default() {
195 let default_router = RouterType::default();
196 assert_eq!(default_router, RouterType::PushRandom);
197 }
198
199 #[test]
200 fn test_router_type_serialization() {
201 let router_round_robin = RouterType::PushRoundRobin;
202 let router_random = RouterType::PushRandom;
203
204 let serialized_round_robin = serde_json::to_string(&router_round_robin).unwrap();
205 let serialized_random = serde_json::to_string(&router_random).unwrap();
206
207 assert_eq!(serialized_round_robin, "\"push_round_robin\"");
208 assert_eq!(serialized_random, "\"push_random\"");
209 }
210
211 #[test]
212 fn test_router_type_deserialization() {
213 let round_robin: RouterType = serde_json::from_str("\"push_round_robin\"").unwrap();
214 let random: RouterType = serde_json::from_str("\"push_random\"").unwrap();
215
216 assert_eq!(round_robin, RouterType::PushRoundRobin);
217 assert_eq!(random, RouterType::PushRandom);
218 }
219
220 #[test]
221 fn test_valid_endpoint_from() {
222 let input = "namespace1/component1/endpoint1";
223 let endpoint = Endpoint::from(input);
224
225 assert_eq!(endpoint.namespace, "namespace1");
226 assert_eq!(endpoint.component, "component1");
227 assert_eq!(endpoint.name, "endpoint1");
228 }
229
230 #[test]
231 fn test_valid_endpoint_from_str() {
232 let input = "namespace2/component2/endpoint2";
233 let endpoint = Endpoint::from_str(input).unwrap();
234
235 assert_eq!(endpoint.namespace, "namespace2");
236 assert_eq!(endpoint.component, "component2");
237 assert_eq!(endpoint.name, "endpoint2");
238 }
239
240 #[test]
241 fn test_valid_endpoint_parse() {
242 let input = "namespace3/component3/endpoint3";
243 let endpoint: Endpoint = input.parse().unwrap();
244
245 assert_eq!(endpoint.namespace, "namespace3");
246 assert_eq!(endpoint.component, "component3");
247 assert_eq!(endpoint.name, "endpoint3");
248 }
249
250 #[test]
251 fn test_endpoint_from() {
252 let result = Endpoint::from("component");
253 assert_eq!(
254 result,
255 vec![DEFAULT_NAMESPACE, "component", DEFAULT_ENDPOINT]
256 );
257 }
258
259 #[test]
260 fn test_namespace_component_endpoint() {
261 let result = Endpoint::from("namespace.component.endpoint");
262 assert_eq!(result, vec!["namespace", "component", "endpoint"]);
263 }
264
265 #[test]
266 fn test_forward_slash_separator() {
267 let result = Endpoint::from("namespace/component");
268 assert_eq!(result, vec!["namespace", "component", DEFAULT_ENDPOINT]);
269 }
270
271 #[test]
272 fn test_multiple_parts() {
273 let result = Endpoint::from("namespace.component.endpoint.other.parts");
274 assert_eq!(
275 result,
276 vec!["namespace", "component", "endpoint_other_parts"]
277 );
278 }
279
280 #[test]
281 fn test_mixed_separators() {
282 let result: Endpoint = "namespace/component.endpoint".into();
284 assert_eq!(result, vec!["namespace", "component", "endpoint"]);
285 }
286
287 #[test]
288 fn test_empty_string() {
289 let result = Endpoint::from("");
290 assert_eq!(
291 result,
292 vec![DEFAULT_NAMESPACE, DEFAULT_COMPONENT, DEFAULT_ENDPOINT]
293 );
294
295 let result = Endpoint::from(" ");
297 assert_eq!(
298 result,
299 vec![DEFAULT_NAMESPACE, DEFAULT_COMPONENT, DEFAULT_ENDPOINT]
300 );
301 }
302}