feat(header): introduce header::Raw (#869)
The Raw type repesents the raw bytes of a header-value. Having a special type allows a couple of benefits: - The exact representation has become private, allowing "uglier" internals. Specifically, since the common case is for a header to only have 1 line of bytes, an enum is used to skip allocating a Vec for only 1 line. Additionally, a Cow<'static, [u8]> is used, so static bytes don't require a copy. Finally, since we can use static bytes, when parsing, we can compare the incoming bytes against a couple of the most common header-values, and possibly remove another copy. - As its own type, the `Headers.set_raw` method can be generic over `Into<Raw>`, which allows for more ergnomic method calls. BREAKING CHANGE: `Header::parse_header` now receives `&Raw`, instead of a `&[Vec<u8>]`. `Raw` provides several methods to ease using it, but may require some changes to existing code.
This commit is contained in:
		| @@ -11,7 +11,7 @@ use std::fmt; | ||||
| use unicase::UniCase; | ||||
| use url::percent_encoding; | ||||
|  | ||||
| use header::{Header, parsing}; | ||||
| use header::{Header, Raw, parsing}; | ||||
| use header::parsing::{parse_extended_value, HTTP_VALUE}; | ||||
| use header::shared::Charset; | ||||
|  | ||||
| @@ -94,7 +94,7 @@ impl Header for ContentDisposition { | ||||
|         NAME | ||||
|     } | ||||
|  | ||||
|     fn parse_header(raw: &[Vec<u8>]) -> ::Result<ContentDisposition> { | ||||
|     fn parse_header(raw: &Raw) -> ::Result<ContentDisposition> { | ||||
|         parsing::from_one_raw_str(raw).and_then(|s: String| { | ||||
|             let mut sections = s.split(';'); | ||||
|             let disposition = match sections.next() { | ||||
| @@ -201,10 +201,10 @@ mod tests { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_parse_header() { | ||||
|         assert!(ContentDisposition::parse_header([b"".to_vec()].as_ref()).is_err()); | ||||
|         assert!(ContentDisposition::parse_header(&"".into()).is_err()); | ||||
|  | ||||
|         let a = [b"form-data; dummy=3; name=upload;\r\n filename=\"sample.png\"".to_vec()]; | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(a.as_ref()).unwrap(); | ||||
|         let a = "form-data; dummy=3; name=upload;\r\n filename=\"sample.png\"".into(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(&a).unwrap(); | ||||
|         let b = ContentDisposition { | ||||
|             disposition: DispositionType::Ext("form-data".to_owned()), | ||||
|             parameters: vec![ | ||||
| @@ -217,8 +217,8 @@ mod tests { | ||||
|         }; | ||||
|         assert_eq!(a, b); | ||||
|  | ||||
|         let a = [b"attachment; filename=\"image.jpg\"".to_vec()]; | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(a.as_ref()).unwrap(); | ||||
|         let a = "attachment; filename=\"image.jpg\"".into(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(&a).unwrap(); | ||||
|         let b = ContentDisposition { | ||||
|             disposition: DispositionType::Attachment, | ||||
|             parameters: vec![ | ||||
| @@ -229,8 +229,8 @@ mod tests { | ||||
|         }; | ||||
|         assert_eq!(a, b); | ||||
|  | ||||
|         let a = [b"attachment; filename*=UTF-8''%c2%a3%20and%20%e2%82%ac%20rates".to_vec()]; | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(a.as_ref()).unwrap(); | ||||
|         let a = "attachment; filename*=UTF-8''%c2%a3%20and%20%e2%82%ac%20rates".into(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(&a).unwrap(); | ||||
|         let b = ContentDisposition { | ||||
|             disposition: DispositionType::Attachment, | ||||
|             parameters: vec![ | ||||
| @@ -245,19 +245,19 @@ mod tests { | ||||
|  | ||||
|     #[test] | ||||
|     fn test_display() { | ||||
|         let a = [b"attachment; filename*=UTF-8'en'%C2%A3%20and%20%E2%82%AC%20rates".to_vec()]; | ||||
|         let as_string = ::std::str::from_utf8(&(a[0])).unwrap(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(a.as_ref()).unwrap(); | ||||
|         let as_string = "attachment; filename*=UTF-8'en'%C2%A3%20and%20%E2%82%AC%20rates"; | ||||
|         let a = as_string.into(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(&a).unwrap(); | ||||
|         let display_rendered = format!("{}",a); | ||||
|         assert_eq!(as_string, display_rendered); | ||||
|  | ||||
|         let a = [b"attachment; filename*=UTF-8''black%20and%20white.csv".to_vec()]; | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(a.as_ref()).unwrap(); | ||||
|         let a = "attachment; filename*=UTF-8''black%20and%20white.csv".into(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(&a).unwrap(); | ||||
|         let display_rendered = format!("{}",a); | ||||
|         assert_eq!("attachment; filename=\"black and white.csv\"".to_owned(), display_rendered); | ||||
|  | ||||
|         let a = [b"attachment; filename=colourful.csv".to_vec()]; | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(a.as_ref()).unwrap(); | ||||
|         let a = "attachment; filename=colourful.csv".into(); | ||||
|         let a: ContentDisposition = ContentDisposition::parse_header(&a).unwrap(); | ||||
|         let display_rendered = format!("{}",a); | ||||
|         assert_eq!("attachment; filename=\"colourful.csv\"".to_owned(), display_rendered); | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user