fix(header): fix panic from headers.remove when typed doesn't match
This commit is contained in:
@@ -57,13 +57,10 @@ impl Item {
|
|||||||
match self.typed.get(tid) {
|
match self.typed.get(tid) {
|
||||||
Some(val) => Some(val),
|
Some(val) => Some(val),
|
||||||
None => {
|
None => {
|
||||||
match parse::<H>(self.raw.as_ref().expect("item.raw must exist")) {
|
parse::<H>(self.raw.as_ref().expect("item.raw must exist")).and_then(|typed| {
|
||||||
Ok(typed) => {
|
unsafe { self.typed.insert(tid, typed); }
|
||||||
unsafe { self.typed.insert(tid, typed); }
|
self.typed.get(tid)
|
||||||
self.typed.get(tid)
|
})
|
||||||
},
|
|
||||||
Err(_) => None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.map(|typed| unsafe { typed.downcast_ref_unchecked() })
|
}.map(|typed| unsafe { typed.downcast_ref_unchecked() })
|
||||||
}
|
}
|
||||||
@@ -71,12 +68,9 @@ impl Item {
|
|||||||
pub fn typed_mut<H: Header>(&mut self) -> Option<&mut H> {
|
pub fn typed_mut<H: Header>(&mut self) -> Option<&mut H> {
|
||||||
let tid = TypeId::of::<H>();
|
let tid = TypeId::of::<H>();
|
||||||
if self.typed.get_mut(tid).is_none() {
|
if self.typed.get_mut(tid).is_none() {
|
||||||
match parse::<H>(self.raw.as_ref().expect("item.raw must exist")) {
|
parse::<H>(self.raw.as_ref().expect("item.raw must exist")).map(|typed| {
|
||||||
Ok(typed) => {
|
unsafe { self.typed.insert(tid, typed); }
|
||||||
unsafe { self.typed.insert(tid, typed); }
|
});
|
||||||
},
|
|
||||||
Err(_) => ()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if self.raw.is_some() && self.typed.get_mut(tid).is_some() {
|
if self.raw.is_some() && self.typed.get_mut(tid).is_some() {
|
||||||
self.raw = OptCell::new(None);
|
self.raw = OptCell::new(None);
|
||||||
@@ -86,10 +80,10 @@ impl Item {
|
|||||||
|
|
||||||
pub fn into_typed<H: Header>(self) -> Option<H> {
|
pub fn into_typed<H: Header>(self) -> Option<H> {
|
||||||
let tid = TypeId::of::<H>();
|
let tid = TypeId::of::<H>();
|
||||||
match self.typed.into_value(tid) {
|
let Item { typed, raw } = self;
|
||||||
Some(val) => Some(val),
|
typed.into_value(tid)
|
||||||
None => parse::<H>(self.raw.as_ref().expect("item.raw must exist")).ok()
|
.or_else(|| raw.as_ref().and_then(parse::<H>))
|
||||||
}.map(|typed| unsafe { typed.downcast_unchecked() })
|
.map(|typed| unsafe { typed.downcast_unchecked() })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_h1(&self, f: &mut Formatter) -> fmt::Result {
|
pub fn write_h1(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
@@ -117,9 +111,9 @@ impl Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn parse<H: Header>(raw: &Raw) -> ::Result<Box<Header + Send + Sync>> {
|
fn parse<H: Header>(raw: &Raw) -> Option<Box<Header + Send + Sync>> {
|
||||||
H::parse_header(raw).map(|h| {
|
H::parse_header(raw).map(|h| {
|
||||||
let h: Box<Header + Send + Sync> = Box::new(h);
|
let h: Box<Header + Send + Sync> = Box::new(h);
|
||||||
h
|
h
|
||||||
})
|
}).ok()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -863,6 +863,12 @@ mod tests {
|
|||||||
let mut headers = Headers::new();
|
let mut headers = Headers::new();
|
||||||
headers.set(ContentLength(10));
|
headers.set(ContentLength(10));
|
||||||
assert_eq!(headers.remove(), Some(ContentLength(10)));
|
assert_eq!(headers.remove(), Some(ContentLength(10)));
|
||||||
|
assert_eq!(headers.len(), 0);
|
||||||
|
|
||||||
|
headers.set(ContentLength(9));
|
||||||
|
assert_eq!(headers.len(), 1);
|
||||||
|
assert!(headers.remove::<CrazyLength>().is_none());
|
||||||
|
assert_eq!(headers.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user