1use crate::proto::KeyValue;
7use core::time::Duration;
8use std::collections::HashMap;
9#[derive(Clone, Default, Debug)]
10pub struct Context {
11 pub metadata: HashMap<String, Vec<String>>,
12 pub timeout_nano: i64,
13}
14
15pub fn with_timeout(i: i64) -> Context {
16 Context {
17 timeout_nano: i,
18 ..Default::default()
19 }
20}
21pub fn with_duration(du: Duration) -> Context {
24 with_timeout(du.as_nanos() as i64)
25}
26
27pub fn with_metadata(md: HashMap<String, Vec<String>>) -> Context {
28 Context {
29 metadata: md,
30 ..Default::default()
31 }
32}
33
34impl Context {
35 pub fn add(&mut self, key: String, value: String) {
37 if let Some(ref mut vl) = self.metadata.get_mut(&key) {
38 vl.push(value);
39 } else {
40 self.metadata.insert(key.to_lowercase(), vec![value]);
41 }
42 }
43
44 pub fn set(&mut self, key: String, value: Vec<String>) {
48 if value.is_empty() {
49 self.metadata.remove(&key);
50 } else {
51 self.metadata.insert(key.to_lowercase(), value);
52 }
53 }
54}
55
56pub fn from_pb(kvs: &Vec<KeyValue>) -> HashMap<String, Vec<String>> {
57 let mut meta: HashMap<String, Vec<String>> = HashMap::new();
58 for kv in kvs {
59 if let Some(ref mut vl) = meta.get_mut(&kv.key) {
60 vl.push(kv.value.clone());
61 } else {
62 meta.insert(kv.key.clone(), vec![kv.value.clone()]);
63 }
64 }
65 meta
66}
67
68pub fn to_pb(kvs: HashMap<String, Vec<String>>) -> Vec<KeyValue> {
69 let mut meta = Vec::with_capacity(kvs.len());
70
71 for (k, vl) in kvs {
72 for v in vl {
73 let key = KeyValue {
74 key: k.clone(),
75 value: v.clone(),
76 ..Default::default()
77 };
78 meta.push(key);
79 }
80 }
81
82 meta
83}
84
85#[cfg(test)]
86mod tests {
87 use crate::context;
88 use crate::proto::KeyValue;
89
90 #[test]
91 fn test_metadata() {
92 let mut src = Vec::new();
94 for i in &[
95 ("key1", "value1-1"),
96 ("key1", "value1-2"),
97 ("key2", "value2"),
98 ] {
99 let key = KeyValue {
100 key: i.0.to_string(),
101 value: i.1.to_string(),
102 ..Default::default()
103 };
104 src.push(key);
105 }
106
107 let dst = context::from_pb(&src);
108 assert_eq!(dst.len(), 2);
109
110 assert_eq!(
111 dst.get("key1"),
112 Some(&vec!["value1-1".to_string(), "value1-2".to_string()])
113 );
114 assert_eq!(dst.get("key2"), Some(&vec!["value2".to_string()]));
115 assert_eq!(dst.get("key3"), None);
116
117 let mut kvs = context::to_pb(dst);
119 kvs.sort_by(|a, b| a.key.partial_cmp(&b.key).unwrap());
120
121 assert_eq!(kvs.len(), 3);
122
123 assert_eq!(kvs[0].key, "key1");
124 assert_eq!(kvs[0].value, "value1-1");
125
126 assert_eq!(kvs[1].key, "key1");
127 assert_eq!(kvs[1].value, "value1-2");
128
129 assert_eq!(kvs[2].key, "key2");
130 assert_eq!(kvs[2].value, "value2");
131 }
132
133 #[test]
134 fn test_context() {
135 let ctx: context::Context = Default::default();
136 assert_eq!(0, ctx.timeout_nano);
137 assert_eq!(ctx.metadata.len(), 0);
138
139 let mut ctx = context::with_duration(core::time::Duration::from_nanos(99));
140 assert_eq!(99, ctx.timeout_nano);
141 assert_eq!(ctx.metadata.len(), 0);
142
143 ctx.add("key1".to_string(), "value1-1".to_string());
144 assert_eq!(ctx.metadata.len(), 1);
145 assert_eq!(
146 ctx.metadata.get("key1"),
147 Some(&vec!["value1-1".to_string()])
148 );
149
150 ctx.add("key1".to_string(), "value1-2".to_string());
151 assert_eq!(ctx.metadata.len(), 1);
152 assert_eq!(
153 ctx.metadata.get("key1"),
154 Some(&vec!["value1-1".to_string(), "value1-2".to_string()])
155 );
156
157 ctx.set("key2".to_string(), vec!["value2".to_string()]);
158 assert_eq!(ctx.metadata.len(), 2);
159 assert_eq!(ctx.metadata.get("key2"), Some(&vec!["value2".to_string()]));
160
161 ctx.set("key1".to_string(), vec![]);
162 assert_eq!(ctx.metadata.len(), 1);
163 assert_eq!(ctx.metadata.get("key1"), None);
164 }
165}