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
use std::fmt::{self, Display};
use std::str::FromStr;
use unicase::UniCase;
pub use self::ConnectionOption::{KeepAlive, Close, ConnectionHeader};
#[derive(Clone, PartialEq, Debug)]
pub enum ConnectionOption {
KeepAlive,
Close,
ConnectionHeader(UniCase<String>),
}
impl FromStr for ConnectionOption {
type Err = ();
fn from_str(s: &str) -> Result<ConnectionOption, ()> {
match s {
"keep-alive" => Ok(KeepAlive),
"close" => Ok(Close),
s => Ok(ConnectionHeader(UniCase(s.to_owned())))
}
}
}
impl Display for ConnectionOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
KeepAlive => "keep-alive",
Close => "close",
ConnectionHeader(UniCase(ref s)) => s.as_ref()
})
}
}
header! {
#[doc="`Connection` header, defined in"]
#[doc="[RFC7230](http://tools.ietf.org/html/rfc7230#section-6.1)"]
#[doc=""]
#[doc="The `Connection` header field allows the sender to indicate desired"]
#[doc="control options for the current connection. In order to avoid"]
#[doc="confusing downstream recipients, a proxy or gateway MUST remove or"]
#[doc="replace any received connection options before forwarding the"]
#[doc="message."]
#[doc=""]
#[doc="# ABNF"]
#[doc="```plain"]
#[doc="Connection = 1#connection-option"]
#[doc="connection-option = token"]
#[doc=""]
#[doc="# Example values"]
#[doc="* `close`"]
#[doc="* `keep-alive`"]
#[doc="* `upgrade`"]
(Connection, "Connection") => (ConnectionOption)+
test_connection {
test_header!(test1, vec![b"close"]);
test_header!(test2, vec![b"keep-alive"]);
test_header!(test3, vec![b"upgrade"]);
}
}
impl Connection {
#[inline]
pub fn close() -> Connection {
Connection(vec![ConnectionOption::Close])
}
#[inline]
pub fn keep_alive() -> Connection {
Connection(vec![ConnectionOption::KeepAlive])
}
}
bench_header!(close, Connection, { vec![b"close".to_vec()] });
bench_header!(keep_alive, Connection, { vec![b"keep-alive".to_vec()] });
bench_header!(header, Connection, { vec![b"authorization".to_vec()] });
#[cfg(test)]
mod tests {
use super::{Connection,ConnectionHeader};
use header::Header;
use unicase::UniCase;
fn parse_option(header: Vec<u8>) -> Connection {
let val = vec![header];
let connection: Connection = Header::parse_header(&val[..]).unwrap();
connection
}
#[test]
fn test_parse() {
assert_eq!(Connection::close(),parse_option(b"close".to_vec()));
assert_eq!(Connection::keep_alive(),parse_option(b"keep-alive".to_vec()));
assert_eq!(Connection(vec![ConnectionHeader(UniCase("upgrade".to_owned()))]),parse_option(b"upgrade".to_vec()));
}
}