opentelemetry/propagation/
mod.rs1use std::collections::HashMap;
23
24pub mod composite;
25pub mod text_map_propagator;
26
27pub use composite::TextMapCompositePropagator;
28pub use text_map_propagator::TextMapPropagator;
29
30pub trait Injector {
32 fn set(&mut self, key: &str, value: String);
34
35 #[allow(unused_variables)]
36 fn reserve(&mut self, additional: usize) {}
38}
39
40pub trait Extractor {
42 fn get(&self, key: &str) -> Option<&str>;
44
45 fn keys(&self) -> Vec<&str>;
47
48 fn get_all(&self, key: &str) -> Option<Vec<&str>> {
50 self.get(key).map(|value| vec![value])
51 }
52}
53
54impl<S: std::hash::BuildHasher> Injector for HashMap<String, String, S> {
55 fn set(&mut self, key: &str, value: String) {
57 self.insert(key.to_lowercase(), value);
58 }
59
60 fn reserve(&mut self, additional: usize) {
62 self.reserve(additional);
63 }
64}
65
66impl<S: std::hash::BuildHasher> Extractor for HashMap<String, String, S> {
67 fn get(&self, key: &str) -> Option<&str> {
69 self.get(&key.to_lowercase()).map(|v| v.as_str())
70 }
71
72 fn keys(&self) -> Vec<&str> {
74 self.keys().map(|k| k.as_str()).collect::<Vec<_>>()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn hash_map_get() {
84 let mut carrier = HashMap::new();
85 carrier.set("headerName", "value".to_string());
86
87 assert_eq!(
88 Extractor::get(&carrier, "HEADERNAME"),
89 Some("value"),
90 "case insensitive extraction"
91 );
92 }
93
94 #[test]
95 fn hash_map_get_all() {
96 let mut carrier = HashMap::new();
97 carrier.set("headerName", "value".to_string());
98
99 assert_eq!(
100 Extractor::get_all(&carrier, "HEADERNAME"),
101 Some(vec!["value"]),
102 "case insensitive get_all extraction"
103 );
104 }
105
106 #[test]
107 fn hash_map_get_all_missing_key() {
108 let mut carrier = HashMap::new();
109 carrier.set("headerName", "value".to_string());
110
111 assert_eq!(
112 Extractor::get_all(&carrier, "missing_key"),
113 None,
114 "case insensitive get_all extraction"
115 );
116 }
117
118 #[test]
119 fn hash_map_keys() {
120 let mut carrier = HashMap::new();
121 carrier.set("headerName1", "value1".to_string());
122 carrier.set("headerName2", "value2".to_string());
123
124 let got = Extractor::keys(&carrier);
125 assert_eq!(got.len(), 2);
126 assert!(got.contains(&"headername1"));
127 assert!(got.contains(&"headername2"));
128 }
129
130 #[test]
131 fn hash_map_injector_reserve() {
132 let mut carrier = HashMap::new();
133
134 Injector::reserve(&mut carrier, 10);
136
137 Injector::set(&mut carrier, "test_key", "test_value".to_string());
139 assert_eq!(Extractor::get(&carrier, "test_key"), Some("test_value"));
140
141 Injector::reserve(&mut carrier, 0);
143 Injector::set(&mut carrier, "another_key", "another_value".to_string());
144 assert_eq!(
145 Extractor::get(&carrier, "another_key"),
146 Some("another_value")
147 );
148
149 let mut new_carrier = HashMap::new();
151 Injector::reserve(&mut new_carrier, 5);
152 let initial_capacity = new_carrier.capacity();
153
154 for i in 0..3 {
156 Injector::set(
157 &mut new_carrier,
158 &format!("key{}", i),
159 format!("value{}", i),
160 );
161 }
162
163 assert!(new_carrier.capacity() >= initial_capacity);
164 assert!(new_carrier.capacity() >= 5);
165 }
166
167 #[test]
168 fn injector_reserve() {
169 struct TestInjector();
171 impl Injector for TestInjector {
172 fn set(&mut self, _key: &str, _value: String) {}
173 }
174 let mut test_injector = TestInjector();
175 Injector::reserve(&mut test_injector, 4711);
176 Injector::set(&mut test_injector, "key", "value".to_string());
177 }
178}