From b4b2fb782e51b2b932e52fab6add7c23a369f1fb Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Wed, 25 Jan 2017 23:41:47 -0800 Subject: [PATCH] feat(header): add Headers::append_raw --- src/header/internals/item.rs | 3 +- src/header/mod.rs | 55 +++++++++++++++++++++++++++++++++--- src/header/raw.rs | 29 +++++++++++-------- 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/header/internals/item.rs b/src/header/internals/item.rs index d5de13641b..a28f162b01 100644 --- a/src/header/internals/item.rs +++ b/src/header/internals/item.rs @@ -33,7 +33,8 @@ impl Item { } #[inline] - pub fn mut_raw(&mut self) -> &mut Raw { + pub fn raw_mut(&mut self) -> &mut Raw { + self.raw(); self.typed = PtrMapCell::new(); unsafe { self.raw.get_mut() diff --git a/src/header/mod.rs b/src/header/mod.rs index 2d478ac59f..8aed5d42d8 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -216,6 +216,17 @@ impl<'a> fmt::Display for ValueString<'a> { } } +struct HeaderValueString<'a, H: Header + 'a>(&'a H); + +impl<'a, H: Header> fmt::Debug for HeaderValueString<'a, H> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str("\"")); + try!(self.0.fmt_multi_header(&mut MultilineFormatter(Multi::Join(true, f)))); + f.write_str("\"") + } +} + struct NewlineReplacer<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>); impl<'a, 'b> fmt::Write for NewlineReplacer<'a, 'b> { @@ -363,7 +374,7 @@ impl Headers { /// /// The field is determined by the type of the value being set. pub fn set(&mut self, value: H) { - trace!("Headers.set( {:?}, {:?} )", header_name::(), HeaderFormatter(&value)); + trace!("Headers.set( {:?}, {:?} )", header_name::(), HeaderValueString(&value)); self.data.insert(HeaderName(UniCase(Cow::Borrowed(header_name::()))), Item::new_typed(Box::new(value))); } @@ -460,6 +471,33 @@ impl Headers { self.data.insert(HeaderName(UniCase(name)), Item::new_raw(value)); } + /// Append a value to raw value of this header. + /// + /// If a header already contains a value, this will add another line to it. + /// + /// If a header doesnot exist for this name, a new one will be created with + /// the value. + /// + /// Example: + /// + /// ``` + /// # use hyper::header::Headers; + /// # let mut headers = Headers::new(); + /// headers.append_raw("x-foo", b"bar".to_vec()); + /// headers.append_raw("x-foo", b"quux".to_vec()); + /// ``` + pub fn append_raw>, V: Into>(&mut self, name: K, value: V) { + let name = name.into(); + let value = value.into(); + trace!("Headers.append_raw( {:?}, {:?} )", name, value); + let name = HeaderName(UniCase(name)); + if let Some(item) = self.data.get_mut(&name) { + item.raw_mut().push(value); + return; + } + self.data.insert(name, Item::new_raw(value)); + } + /// Remove a header by name. pub fn remove_raw(&mut self, name: &str) { trace!("Headers.remove_raw( {:?} )", name); @@ -583,7 +621,7 @@ impl<'a> Extend<(&'a str, MemSlice)> for Headers { entry.insert(Item::new_raw(self::raw::parsed(value))); } Entry::Occupied(entry) => { - self::raw::push(entry.into_mut().mut_raw(), value); + self::raw::push(entry.into_mut().raw_mut(), value); } }; } @@ -625,8 +663,7 @@ deprecated! { impl<'a, H: Header> fmt::Display for HeaderFormatter<'a, H> { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut multi = MultilineFormatter(Multi::Join(true, f)); - self.0.fmt_multi_header(&mut multi) + fmt::Debug::fmt(&HeaderValueString(self.0), f) } } @@ -806,6 +843,16 @@ mod tests { assert_eq!(headers.get(), Some(&ContentLength(20))); } + #[test] + fn test_append_raw() { + let mut headers = Headers::new(); + headers.set(ContentLength(10)); + headers.append_raw("content-LENGTH", b"20".to_vec()); + assert_eq!(headers.get_raw("Content-length").unwrap(), &[b"10".to_vec(), b"20".to_vec()][..]); + headers.append_raw("x-foo", "bar"); + assert_eq!(headers.get_raw("x-foo").unwrap(), &[b"bar".to_vec()][..]); + } + #[test] fn test_remove_raw() { let mut headers = Headers::new(); diff --git a/src/header/raw.rs b/src/header/raw.rs index 5e93d677d9..c122b3fb2c 100644 --- a/src/header/raw.rs +++ b/src/header/raw.rs @@ -36,8 +36,16 @@ impl Raw { } /// Append a line to this `Raw` header value. - pub fn push(&mut self, val: &[u8]) { - self.push_line(maybe_literal(val.into())); + pub fn push>(&mut self, val: V) { + let raw = val.into(); + match raw.0 { + Lines::One(one) => self.push_line(one), + Lines::Many(lines) => { + for line in lines { + self.push_line(line); + } + } + } } fn push_line(&mut self, line: Line) { @@ -121,27 +129,26 @@ impl From>> for Raw { impl From for Raw { #[inline] fn from(val: String) -> Raw { - let vec: Vec = val.into(); - vec.into() + Raw::from(val.into_bytes()) } } impl From> for Raw { #[inline] fn from(val: Vec) -> Raw { - Raw(Lines::One(Line::from(val))) + Raw(Lines::One(maybe_literal(val.into()))) } } -impl From<&'static str> for Raw { - fn from(val: &'static str) -> Raw { - Raw(Lines::One(Line::Static(val.as_bytes()))) +impl<'a> From<&'a str> for Raw { + fn from(val: &'a str) -> Raw { + Raw::from(val.as_bytes()) } } -impl From<&'static [u8]> for Raw { - fn from(val: &'static [u8]) -> Raw { - Raw(Lines::One(Line::Static(val))) +impl<'a> From<&'a [u8]> for Raw { + fn from(val: &'a [u8]) -> Raw { + Raw(Lines::One(maybe_literal(val.into()))) } }