wtransport_proto/
headers.rs1use crate::error::ErrorCode;
2use crate::frame::Frame;
3use crate::frame::FrameKind;
4use crate::qpack::Decoder;
5use crate::qpack::Encoder;
6use std::borrow::Cow;
7use std::collections::HashMap;
8
9#[derive(Debug)]
11pub struct Headers(HashMap<String, String>);
12
13impl Headers {
14 pub fn with_frame(frame: &Frame) -> Result<Self, ErrorCode> {
20 assert!(matches!(frame.kind(), FrameKind::Headers));
21
22 let headers = Decoder::decode(frame.payload()).map_err(|_| ErrorCode::Decompression)?;
23
24 Ok(Self(headers))
25 }
26
27 pub fn generate_frame(&self) -> Frame<'static> {
29 let payload = Encoder::encode(&self.0);
30 Frame::new_headers(Cow::Owned(payload.to_vec()))
31 }
32
33 #[inline(always)]
35 pub fn get<K>(&self, key: K) -> Option<&str>
36 where
37 K: AsRef<str>,
38 {
39 self.0.get(key.as_ref()).map(|s| s.as_str())
40 }
41
42 #[inline(always)]
46 pub fn insert<K, V>(&mut self, key: K, value: V)
47 where
48 K: ToString,
49 V: ToString,
50 {
51 self.0.insert(key.to_string(), value.to_string());
52 }
53}
54
55impl<K, V> FromIterator<(K, V)> for Headers
56where
57 K: ToString,
58 V: ToString,
59{
60 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
61 Self(
62 iter.into_iter()
63 .map(|(k, v)| (k.to_string(), v.to_string()))
64 .collect(),
65 )
66 }
67}
68
69impl AsRef<HashMap<String, String>> for Headers {
70 fn as_ref(&self) -> &HashMap<String, String> {
71 &self.0
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn generate_frame_kind() {
81 let headers = [("key1", "value1"), ("key2", "value2")]
82 .into_iter()
83 .collect::<Headers>();
84
85 let frame = headers.generate_frame();
86 assert!(matches!(frame.kind(), FrameKind::Headers));
87 }
88
89 #[test]
90 fn get() {
91 let headers = [("key1", "value1"), ("key2", "value2")]
92 .into_iter()
93 .collect::<Headers>();
94
95 assert_eq!(headers.get("key1"), Some("value1"));
96 assert_eq!(headers.get("key2"), Some("value2"));
97 assert_eq!(headers.get("key3"), None);
98 }
99
100 #[test]
101 fn insert() {
102 let mut headers = [("key1", "value1"), ("key2", "value2")]
103 .into_iter()
104 .collect::<Headers>();
105
106 assert_eq!(headers.get("key1"), Some("value1"));
107 headers.insert("key1", "value1bis");
108 assert_eq!(headers.get("key1"), Some("value1bis"));
109
110 assert_eq!(headers.get("key3"), None);
111 headers.insert("key3", "value3");
112 assert_eq!(headers.get("key3"), Some("value3"));
113 }
114
115 #[test]
116 fn idempotence() {
117 let headers = [("key1", "value1"), ("key2", "value2")]
118 .into_iter()
119 .collect::<Headers>();
120
121 let frame = headers.generate_frame();
122
123 assert_eq!(
124 headers.as_ref(),
125 Headers::with_frame(&frame).unwrap().as_ref()
126 );
127 }
128}