Files
base64
byteorder
bytes
cfg_if
crossbeam_deque
crossbeam_epoch
crossbeam_queue
crossbeam_utils
fnv
futures
futures_cpupool
httparse
hyper
iovec
language_tags
lazy_static
libc
lock_api
log
maybe_uninit
memoffset
mime
mio
mio_uds
net2
num_cpus
parking_lot
parking_lot_core
percent_encoding
proc_macro2
quote
rand
relay
rfsapi
safemem
scoped_tls
scopeguard
serde
serde_derive
slab
smallvec
syn
take
time
tokio
tokio_codec
tokio_core
tokio_current_thread
tokio_executor
tokio_fs
tokio_io
tokio_proto
tokio_reactor
tokio_service
tokio_sync
tokio_tcp
tokio_threadpool
tokio_timer
tokio_udp
tokio_uds
try_lock
unicase
unicode_xid
want
  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
use std::any::Any;
use std::any::TypeId;
use std::fmt;
use std::str::from_utf8;

use super::cell::{OptCell, PtrMapCell};
use header::{Header, Formatter, Multi, raw, Raw};


#[derive(Clone)]
pub struct Item {
    raw: OptCell<Raw>,
    typed: PtrMapCell<Header + Send + Sync>
}

impl Item {
    #[inline]
    pub fn new_raw(data: Raw) -> Item {
        Item {
            raw: OptCell::new(Some(data)),
            typed: PtrMapCell::new(),
        }
    }

    #[inline]

    pub fn new_typed<H: Header>(val: H) -> Item {
        Item {
            raw: OptCell::new(None),
            typed: PtrMapCell::with_one(TypeId::of::<H>(), Box::new(val)),
        }
    }

    #[inline]
    pub fn raw_mut(&mut self) -> &mut Raw {
        self.raw();
        self.typed = PtrMapCell::new();
        unsafe {
            self.raw.get_mut()
        }
    }

    pub fn raw(&self) -> &Raw {
        if let Some(ref raw) = *self.raw {
            return raw;
        }

        let mut raw = raw::new();
        self.write_h1(&mut Formatter(Multi::Raw(&mut raw))).expect("fmt failed");
        self.raw.set(raw);

        self.raw.as_ref().unwrap()
    }

    pub fn typed<H: Header + Any>(&self) -> Option<&H> {
        let tid = TypeId::of::<H>();
        match self.typed.get(tid) {
            Some(val) => Some(val),
            None => {
                parse::<H>(self.raw.as_ref().expect("item.raw must exist")).and_then(|typed| {
                    unsafe { self.typed.insert(tid, typed); }
                    self.typed.get(tid)
                })
            }
        }.map(|typed| unsafe { typed.downcast_ref_unchecked() })
    }

    pub fn typed_mut<H: Header>(&mut self) -> Option<&mut H> {
        let tid = TypeId::of::<H>();
        if self.typed.get_mut(tid).is_none() {
            parse::<H>(self.raw.as_ref().expect("item.raw must exist")).map(|typed| {
                unsafe { self.typed.insert(tid, typed); }
            });
        }
        if self.raw.is_some() && self.typed.get_mut(tid).is_some() {
            self.raw = OptCell::new(None);
        }
        self.typed.get_mut(tid).map(|typed| unsafe { typed.downcast_mut_unchecked() })
    }

    pub fn into_typed<H: Header>(self) -> Option<H> {
        let tid = TypeId::of::<H>();
        let Item { typed, raw } = self;
        typed.into_value(tid)
            .or_else(|| raw.as_ref().and_then(parse::<H>))
            .map(|typed| unsafe { typed.downcast_unchecked() })
    }

    pub fn write_h1(&self, f: &mut Formatter) -> fmt::Result {
        match *self.raw {
            Some(ref raw) => {
                for part in raw.iter() {
                    match from_utf8(&part[..]) {
                        Ok(s) => {
                            try!(f.fmt_line(&s));
                        },
                        Err(_) => {
                            error!("raw header value is not utf8, value={:?}", part);
                            return Err(fmt::Error);
                        }
                    }
                }
                Ok(())
            },
            None => {
                let typed = unsafe { self.typed.one() };
                typed.fmt_header(f)
            }
        }
    }
}

#[inline]
fn parse<H: Header>(raw: &Raw) -> Option<Box<Header + Send + Sync>> {
    H::parse_header(raw).map(|h| {
        let h: Box<Header + Send + Sync> = Box::new(h);
        h
    }).ok()
}