hyper_sync/header/common/
origin.rs1use std::borrow::Cow;
2use std::fmt;
3use std::str::FromStr;
4
5use header::{Header, Raw, Host};
6use header::parsing::from_one_raw_str;
7
8#[derive(PartialEq, Clone, Debug)]
38pub struct Origin(OriginOrNull);
39
40#[derive(PartialEq, Clone, Debug)]
41enum OriginOrNull {
42 Origin {
43 scheme: Cow<'static,str>,
45 host: Host,
47 },
48 Null,
49}
50
51impl Origin {
52 pub fn new<S: Into<Cow<'static,str>>, H: Into<Cow<'static,str>>>(scheme: S, hostname: H, port: Option<u16>) -> Origin{
54 Origin(OriginOrNull::Origin {
55 scheme: scheme.into(),
56 host: Host::new(hostname, port),
57 })
58 }
59
60 pub fn null() -> Origin {
62 Origin(OriginOrNull::Null)
63 }
64
65 pub fn is_null(&self) -> bool {
67 match self {
68 &Origin(OriginOrNull::Null) => true,
69 _ => false,
70 }
71 }
72
73 pub fn scheme(&self) -> Option<&str> {
81 match self {
82 &Origin(OriginOrNull::Origin { ref scheme, .. }) => Some(&scheme),
83 _ => None,
84 }
85 }
86
87 pub fn host(&self) -> Option<&Host> {
95 match self {
96 &Origin(OriginOrNull::Origin { ref host, .. }) => Some(&host),
97 _ => None,
98 }
99 }
100}
101
102impl Header for Origin {
103 fn header_name() -> &'static str {
104 static NAME: &'static str = "Origin";
105 NAME
106 }
107
108 fn parse_header(raw: &Raw) -> ::Result<Origin> {
109 from_one_raw_str(raw)
110 }
111
112 fn fmt_header(&self, f: &mut ::header::Formatter) -> fmt::Result {
113 f.fmt_line(self)
114 }
115}
116
117static HTTP : &'static str = "http";
118static HTTPS : &'static str = "https";
119
120impl FromStr for Origin {
121 type Err = ::Error;
122
123 fn from_str(s: &str) -> ::Result<Origin> {
124 let idx = match s.find("://") {
125 Some(idx) => idx,
126 None => return Err(::Error::Header)
127 };
128 let (scheme, etc) = (&s[..idx], &s[idx + 3..]);
130 let host = try!(Host::from_str(etc));
131 let scheme = match scheme {
132 "http" => Cow::Borrowed(HTTP),
133 "https" => Cow::Borrowed(HTTPS),
134 s => Cow::Owned(s.to_owned())
135 };
136
137 Ok(Origin(OriginOrNull::Origin {
138 scheme: scheme,
139 host: host
140 }))
141 }
142}
143
144impl fmt::Display for Origin {
145 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146 match self.0 {
147 OriginOrNull::Origin { ref scheme, ref host } => write!(f, "{}://{}", scheme, host),
148 OriginOrNull::Null => f.write_str("null")
151 }
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::Origin;
158 use header::Header;
159 use std::borrow::Cow;
160
161 macro_rules! assert_borrowed{
162 ($expr : expr) => {
163 match $expr {
164 Cow::Owned(ref v) => panic!("assertion failed: `{}` owns {:?}", stringify!($expr), v),
165 _ => {}
166 }
167 }
168 }
169
170 #[test]
171 fn test_origin() {
172 let origin : Origin = Header::parse_header(&vec![b"http://foo.com".to_vec()].into()).unwrap();
173 assert_eq!(&origin, &Origin::new("http", "foo.com", None));
174 assert_borrowed!(origin.scheme().unwrap().into());
175
176 let origin : Origin = Header::parse_header(&vec![b"https://foo.com:443".to_vec()].into()).unwrap();
177 assert_eq!(&origin, &Origin::new("https", "foo.com", Some(443)));
178 assert_borrowed!(origin.scheme().unwrap().into());
179 }
180}
181
182bench_header!(bench, Origin, { vec![b"https://foo.com".to_vec()] });