1use std::convert::TryFrom;
2use std::fmt;
3
4use http::uri::Authority;
5use http::{HeaderName, HeaderValue};
6
7use crate::{Error, Header};
8
9#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd)]
11pub struct Host(Authority);
12
13impl Host {
14 pub fn hostname(&self) -> &str {
16 self.0.host()
17 }
18
19 pub fn port(&self) -> Option<u16> {
21 self.0.port_u16()
22 }
23}
24
25impl Header for Host {
26 fn name() -> &'static HeaderName {
27 &::http::header::HOST
28 }
29
30 fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, Error> {
31 values
32 .next()
33 .cloned()
34 .and_then(|val| Authority::try_from(val.as_bytes()).ok())
35 .map(Host)
36 .ok_or_else(Error::invalid)
37 }
38
39 fn encode<E: Extend<HeaderValue>>(&self, values: &mut E) {
40 let bytes = self.0.as_str().as_bytes();
41 let val = HeaderValue::from_bytes(bytes).expect("Authority is a valid HeaderValue");
42
43 values.extend(::std::iter::once(val));
44 }
45}
46
47impl From<Authority> for Host {
48 fn from(auth: Authority) -> Host {
49 Host(auth)
50 }
51}
52
53impl fmt::Display for Host {
54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 fmt::Display::fmt(&self.0, f)
56 }
57}