Skip to content

Commit 58ad74e

Browse files
committed
move Headers to own file
1 parent 8ac49eb commit 58ad74e

File tree

2 files changed

+178
-171
lines changed

2 files changed

+178
-171
lines changed

src/headers/headers.rs

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
//! HTTP headers.
2+
3+
use std::collections::HashMap;
4+
use std::convert::TryInto;
5+
use std::iter::IntoIterator;
6+
7+
use crate::headers::{
8+
HeaderName, HeaderValues, IntoIter, Iter, IterMut, Names, ToHeaderValues, Values,
9+
};
10+
11+
/// A collection of HTTP Headers.
12+
#[derive(Debug, Clone)]
13+
pub struct Headers {
14+
pub(crate) headers: HashMap<HeaderName, HeaderValues>,
15+
}
16+
17+
impl Headers {
18+
/// Create a new instance.
19+
pub(crate) fn new() -> Self {
20+
Self {
21+
headers: HashMap::new(),
22+
}
23+
}
24+
25+
/// Insert a header into the headers.
26+
///
27+
/// Not that this will replace all header values for a given header name.
28+
/// If you wish to add header values for a header name that already exists
29+
/// use `Headers::append`
30+
pub fn insert(
31+
&mut self,
32+
name: impl TryInto<HeaderName>,
33+
values: impl ToHeaderValues,
34+
) -> crate::Result<Option<HeaderValues>> {
35+
let name = name
36+
.try_into()
37+
.map_err(|_| crate::format_err!("Could not convert into header name"))?;
38+
let values: HeaderValues = values.to_header_values()?.collect();
39+
Ok(self.headers.insert(name, values))
40+
}
41+
42+
/// Append a header to the headers.
43+
///
44+
/// Unlike `insert` this function will not override the contents of a header, but insert a
45+
/// header if there aren't any. Or else append to the existing list of headers.
46+
pub fn append(
47+
&mut self,
48+
name: impl TryInto<HeaderName>,
49+
values: impl ToHeaderValues,
50+
) -> crate::Result<()> {
51+
let name = name
52+
.try_into()
53+
.map_err(|_| crate::format_err!("Could not convert into header name"))?;
54+
match self.get_mut(&name) {
55+
Some(headers) => {
56+
let mut values: HeaderValues = values.to_header_values()?.collect();
57+
headers.append(&mut values);
58+
}
59+
None => {
60+
self.insert(name, values)?;
61+
}
62+
}
63+
Ok(())
64+
}
65+
66+
/// Get a reference to a header.
67+
pub fn get(&self, name: &HeaderName) -> Option<&HeaderValues> {
68+
self.headers.get(name)
69+
}
70+
71+
/// Get a mutable reference to a header.
72+
pub fn get_mut(&mut self, name: &HeaderName) -> Option<&mut HeaderValues> {
73+
self.headers.get_mut(name)
74+
}
75+
76+
/// Remove a header.
77+
pub fn remove(&mut self, name: &HeaderName) -> Option<HeaderValues> {
78+
self.headers.remove(name)
79+
}
80+
81+
/// An iterator visiting all header pairs in arbitrary order.
82+
pub fn iter(&self) -> Iter<'_> {
83+
Iter {
84+
inner: self.headers.iter(),
85+
}
86+
}
87+
88+
/// An iterator visiting all header pairs in arbitrary order, with mutable references to the
89+
/// values.
90+
pub fn iter_mut(&mut self) -> IterMut<'_> {
91+
IterMut {
92+
inner: self.headers.iter_mut(),
93+
}
94+
}
95+
96+
/// An iterator visiting all header names in arbitrary order.
97+
pub fn names(&self) -> Names<'_> {
98+
Names {
99+
inner: self.headers.keys(),
100+
}
101+
}
102+
103+
/// An iterator visiting all header values in arbitrary order.
104+
pub fn values(&self) -> Values<'_> {
105+
Values::new(self.headers.values())
106+
}
107+
}
108+
109+
impl IntoIterator for Headers {
110+
type Item = (HeaderName, HeaderValues);
111+
type IntoIter = IntoIter;
112+
113+
/// Returns a iterator of references over the remaining items.
114+
#[inline]
115+
fn into_iter(self) -> Self::IntoIter {
116+
IntoIter {
117+
inner: self.headers.into_iter(),
118+
}
119+
}
120+
}
121+
122+
impl<'a> IntoIterator for &'a Headers {
123+
type Item = (&'a HeaderName, &'a HeaderValues);
124+
type IntoIter = Iter<'a>;
125+
126+
#[inline]
127+
fn into_iter(self) -> Self::IntoIter {
128+
self.iter()
129+
}
130+
}
131+
132+
impl<'a> IntoIterator for &'a mut Headers {
133+
type Item = (&'a HeaderName, &'a mut HeaderValues);
134+
type IntoIter = IterMut<'a>;
135+
136+
#[inline]
137+
fn into_iter(self) -> Self::IntoIter {
138+
self.iter_mut()
139+
}
140+
}
141+
142+
#[cfg(test)]
143+
mod tests {
144+
use super::*;
145+
use std::str::FromStr;
146+
147+
const STATIC_HEADER: HeaderName = HeaderName::from_lowercase_str("hello");
148+
149+
#[test]
150+
fn test_header_name_static_non_static() -> crate::Result<()> {
151+
let static_header = HeaderName::from_lowercase_str("hello");
152+
let non_static_header = HeaderName::from_str("hello")?;
153+
154+
let mut headers = Headers::new();
155+
headers.append(STATIC_HEADER, "foo0")?;
156+
headers.append(static_header.clone(), "foo1")?;
157+
headers.append(non_static_header.clone(), "foo2")?;
158+
159+
assert_eq!(
160+
&headers.get(&STATIC_HEADER).unwrap()[..],
161+
&["foo0", "foo1", "foo2",][..]
162+
);
163+
164+
assert_eq!(
165+
&headers.get(&static_header).unwrap()[..],
166+
&["foo0", "foo1", "foo2",][..]
167+
);
168+
169+
assert_eq!(
170+
&headers.get(&non_static_header).unwrap()[..],
171+
&["foo0", "foo1", "foo2",][..]
172+
);
173+
174+
Ok(())
175+
}
176+
}

src/headers/mod.rs

Lines changed: 2 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
//! HTTP headers.
22
3-
use std::collections::HashMap;
4-
use std::convert::TryInto;
5-
use std::iter::IntoIterator;
6-
73
mod constants;
84
mod header_name;
95
mod header_value;
106
mod header_values;
7+
mod headers;
118
mod into_iter;
129
mod iter;
1310
mod iter_mut;
@@ -19,176 +16,10 @@ pub use constants::*;
1916
pub use header_name::HeaderName;
2017
pub use header_value::HeaderValue;
2118
pub use header_values::HeaderValues;
19+
pub use headers::Headers;
2220
pub use into_iter::IntoIter;
2321
pub use iter::Iter;
2422
pub use iter_mut::IterMut;
2523
pub use names::Names;
2624
pub use to_header_values::ToHeaderValues;
2725
pub use values::Values;
28-
29-
/// A collection of HTTP Headers.
30-
#[derive(Debug, Clone)]
31-
pub struct Headers {
32-
pub(crate) headers: HashMap<HeaderName, HeaderValues>,
33-
}
34-
35-
impl Headers {
36-
/// Create a new instance.
37-
pub(crate) fn new() -> Self {
38-
Self {
39-
headers: HashMap::new(),
40-
}
41-
}
42-
43-
/// Insert a header into the headers.
44-
///
45-
/// Not that this will replace all header values for a given header name.
46-
/// If you wish to add header values for a header name that already exists
47-
/// use `Headers::append`
48-
pub fn insert(
49-
&mut self,
50-
name: impl TryInto<HeaderName>,
51-
values: impl ToHeaderValues,
52-
) -> crate::Result<Option<HeaderValues>> {
53-
let name = name
54-
.try_into()
55-
.map_err(|_| crate::format_err!("Could not convert into header name"))?;
56-
let values: HeaderValues = values.to_header_values()?.collect();
57-
Ok(self.headers.insert(name, values))
58-
}
59-
60-
/// Append a header to the headers.
61-
///
62-
/// Unlike `insert` this function will not override the contents of a header, but insert a
63-
/// header if there aren't any. Or else append to the existing list of headers.
64-
pub fn append(
65-
&mut self,
66-
name: impl TryInto<HeaderName>,
67-
values: impl ToHeaderValues,
68-
) -> crate::Result<()> {
69-
let name = name
70-
.try_into()
71-
.map_err(|_| crate::format_err!("Could not convert into header name"))?;
72-
match self.get_mut(&name) {
73-
Some(headers) => {
74-
let mut values: HeaderValues = values.to_header_values()?.collect();
75-
headers.append(&mut values);
76-
}
77-
None => {
78-
self.insert(name, values)?;
79-
}
80-
}
81-
Ok(())
82-
}
83-
84-
/// Get a reference to a header.
85-
pub fn get(&self, name: &HeaderName) -> Option<&HeaderValues> {
86-
self.headers.get(name)
87-
}
88-
89-
/// Get a mutable reference to a header.
90-
pub fn get_mut(&mut self, name: &HeaderName) -> Option<&mut HeaderValues> {
91-
self.headers.get_mut(name)
92-
}
93-
94-
/// Remove a header.
95-
pub fn remove(&mut self, name: &HeaderName) -> Option<HeaderValues> {
96-
self.headers.remove(name)
97-
}
98-
99-
/// An iterator visiting all header pairs in arbitrary order.
100-
pub fn iter(&self) -> Iter<'_> {
101-
Iter {
102-
inner: self.headers.iter(),
103-
}
104-
}
105-
106-
/// An iterator visiting all header pairs in arbitrary order, with mutable references to the
107-
/// values.
108-
pub fn iter_mut(&mut self) -> IterMut<'_> {
109-
IterMut {
110-
inner: self.headers.iter_mut(),
111-
}
112-
}
113-
114-
/// An iterator visiting all header names in arbitrary order.
115-
pub fn names(&self) -> Names<'_> {
116-
Names {
117-
inner: self.headers.keys(),
118-
}
119-
}
120-
121-
/// An iterator visiting all header values in arbitrary order.
122-
pub fn values(&self) -> Values<'_> {
123-
Values::new(self.headers.values())
124-
}
125-
}
126-
127-
impl IntoIterator for Headers {
128-
type Item = (HeaderName, HeaderValues);
129-
type IntoIter = IntoIter;
130-
131-
/// Returns a iterator of references over the remaining items.
132-
#[inline]
133-
fn into_iter(self) -> Self::IntoIter {
134-
IntoIter {
135-
inner: self.headers.into_iter(),
136-
}
137-
}
138-
}
139-
140-
impl<'a> IntoIterator for &'a Headers {
141-
type Item = (&'a HeaderName, &'a HeaderValues);
142-
type IntoIter = Iter<'a>;
143-
144-
#[inline]
145-
fn into_iter(self) -> Self::IntoIter {
146-
self.iter()
147-
}
148-
}
149-
150-
impl<'a> IntoIterator for &'a mut Headers {
151-
type Item = (&'a HeaderName, &'a mut HeaderValues);
152-
type IntoIter = IterMut<'a>;
153-
154-
#[inline]
155-
fn into_iter(self) -> Self::IntoIter {
156-
self.iter_mut()
157-
}
158-
}
159-
160-
#[cfg(test)]
161-
mod tests {
162-
use super::*;
163-
use std::str::FromStr;
164-
165-
const STATIC_HEADER: HeaderName = HeaderName::from_lowercase_str("hello");
166-
167-
#[test]
168-
fn test_header_name_static_non_static() -> crate::Result<()> {
169-
let static_header = HeaderName::from_lowercase_str("hello");
170-
let non_static_header = HeaderName::from_str("hello")?;
171-
172-
let mut headers = Headers::new();
173-
headers.append(STATIC_HEADER, "foo0")?;
174-
headers.append(static_header.clone(), "foo1")?;
175-
headers.append(non_static_header.clone(), "foo2")?;
176-
177-
assert_eq!(
178-
&headers.get(&STATIC_HEADER).unwrap()[..],
179-
&["foo0", "foo1", "foo2",][..]
180-
);
181-
182-
assert_eq!(
183-
&headers.get(&static_header).unwrap()[..],
184-
&["foo0", "foo1", "foo2",][..]
185-
);
186-
187-
assert_eq!(
188-
&headers.get(&non_static_header).unwrap()[..],
189-
&["foo0", "foo1", "foo2",][..]
190-
);
191-
192-
Ok(())
193-
}
194-
}

0 commit comments

Comments
 (0)