-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheaders.rs
162 lines (152 loc) · 4.75 KB
/
headers.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use crate::util::escape_and_elide;
use crate::AsciiString;
use core::fmt::{Debug, Display, Formatter};
use std::ops::{Deref, DerefMut};
#[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Header {
pub name: AsciiString,
pub value: AsciiString,
}
impl Header {
#[must_use]
pub fn new(name: AsciiString, value: AsciiString) -> Self {
Self { name, value }
}
}
impl Debug for Header {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"Header({}:{})",
escape_and_elide(self.name.as_bytes(), 30),
escape_and_elide(self.value.as_bytes(), 1000)
)
}
}
impl Display for Header {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "{}:{}", self.name.as_str(), self.value.as_str())
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct HeaderList(pub Vec<Header>);
impl HeaderList {
#[must_use]
pub fn new() -> Self {
Self(Vec::new())
}
/// Adds a header.
///
/// You can call this multiple times to add multiple headers with the same name.
///
/// The [HTTP spec](https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4)
/// limits header names to US-ASCII and header values to US-ASCII or ISO-8859-1.
///
/// # Panics
/// Panics when `name` is not US-ASCII.
pub fn add(&mut self, name: impl AsRef<str>, value: AsciiString) {
self.0
.push(Header::new(name.as_ref().try_into().unwrap(), value));
}
/// Searches for a header that matches `name`.
/// Uses a case-insensitive comparison.
///
/// Returns the value of the header.
///
/// Returns `None` when multiple headers matched or none matched.
pub fn get_only(&self, name: impl AsRef<str>) -> Option<&AsciiString> {
let mut value = None;
for header in &self.0 {
if header.name.eq_ignore_ascii_case(name.as_ref()) {
if value.is_some() {
return None;
}
value = Some(&header.value);
}
}
value
}
/// Looks for headers with names that match `name`.
/// Uses a case-insensitive comparison.
/// Returns the values of the matching headers.
pub fn get_all(&self, name: impl AsRef<str>) -> Vec<&AsciiString> {
let mut headers = Vec::new();
for header in &self.0 {
if header.name.eq_ignore_ascii_case(name.as_ref()) {
headers.push(&header.value);
}
}
headers
}
/// Removes all headers with the specified `name`.
/// Uses a case-insensitive comparison.
///
/// When only one header matched, returns the value of that header.
///
/// Returns `None` when multiple headers matched or none matched.
// TODO: Make this return `Result<Option<AsciiString>, DuplicateHeader>`.
pub fn remove_only(&mut self, name: impl AsRef<str>) -> Option<AsciiString> {
let mut iter = self.remove_all(name).into_iter();
match (iter.next(), iter.next()) {
(Some(value), None) => Some(value),
_ => None,
}
}
/// Removes all headers with the specified `name`.
/// Uses a case-insensitive comparison.
///
/// Returns the values of the headers.
pub fn remove_all(&mut self, name: impl AsRef<str>) -> Vec<AsciiString> {
let mut values = Vec::new();
let mut n = 0;
while n < self.0.len() {
if self.0[n].name.eq_ignore_ascii_case(name.as_ref()) {
let header = self.0.swap_remove(n);
values.push(header.value);
} else {
n += 1;
}
}
values
}
}
impl Debug for HeaderList {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
let mut strings: Vec<String> = self
.iter()
.map(|h| format!("{}: {:?}", h.name, h.value.as_str()))
.collect();
strings.sort();
write!(f, "{{{}}}", strings.join(", "),)
}
}
impl Default for HeaderList {
fn default() -> Self {
Self::new()
}
}
impl Deref for HeaderList {
type Target = Vec<Header>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for HeaderList {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'x> IntoIterator for &'x HeaderList {
type Item = &'x Header;
type IntoIter = core::slice::Iter<'x, Header>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'x> IntoIterator for &'x mut HeaderList {
type Item = &'x mut Header;
type IntoIter = core::slice::IterMut<'x, Header>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter_mut()
}
}