chore(headers): use HeaderValue::from for content-length (#1583)
This commit is contained in:
		
				
					committed by
					
						 Sean McArthur
						Sean McArthur
					
				
			
			
				
	
			
			
			
						parent
						
							d7436cfbe0
						
					
				
				
					commit
					91b08d09e4
				
			| @@ -1,13 +1,8 @@ | |||||||
| use std::mem; |  | ||||||
|  |  | ||||||
| use bytes::BytesMut; | use bytes::BytesMut; | ||||||
| use http::HeaderMap; | use http::HeaderMap; | ||||||
| use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING}; | use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING}; | ||||||
| use http::header::{HeaderValue, OccupiedEntry, ValueIter}; | use http::header::{HeaderValue, OccupiedEntry, ValueIter}; | ||||||
|  |  | ||||||
| /// Maximum number of bytes needed to serialize a u64 into ASCII decimal. |  | ||||||
| const MAX_DECIMAL_U64_BYTES: usize = 20; |  | ||||||
|  |  | ||||||
| pub fn connection_keep_alive(value: &HeaderValue) -> bool { | pub fn connection_keep_alive(value: &HeaderValue) -> bool { | ||||||
|     connection_has(value, "keep-alive") |     connection_has(value, "keep-alive") | ||||||
| } | } | ||||||
| @@ -68,39 +63,11 @@ pub fn content_length_parse_all_values(values: ValueIter<HeaderValue>) -> Option | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn content_length_value(len: u64) -> HeaderValue { |  | ||||||
|     let mut len_buf = if mem::size_of::<BytesMut>() - 1 < MAX_DECIMAL_U64_BYTES { |  | ||||||
|         // when ptr size is 32bits... |  | ||||||
|         // max bytes don't fit inline, but the likelihood of the length |  | ||||||
|         // actually needing that many bytes is super tiny. So, only |  | ||||||
|         // allocate if we really need to. |  | ||||||
|         // constant version of 10.pow(15) - 1... |  | ||||||
|         const MAX_DECIMAL_INLINE: u64 = 999_999_999_999_999; |  | ||||||
|         if len <= MAX_DECIMAL_INLINE { |  | ||||||
|             // Still fits inline of 15 bytes... |  | ||||||
|             BytesMut::new() |  | ||||||
|         } else { |  | ||||||
|             // the number is huge, and doesn't fit into 15 bytes (on 32bit), |  | ||||||
|             // so we gotta allocate ;_; |  | ||||||
|             BytesMut::with_capacity(MAX_DECIMAL_U64_BYTES) |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         // max bytes fit inline |  | ||||||
|         BytesMut::with_capacity(MAX_DECIMAL_U64_BYTES) |  | ||||||
|     }; |  | ||||||
|     ::itoa::fmt(&mut len_buf, len) |  | ||||||
|         .expect("BytesMut can hold a decimal u64"); |  | ||||||
|     // safe because u64 Display is ascii numerals |  | ||||||
|     unsafe { |  | ||||||
|         HeaderValue::from_shared_unchecked(len_buf.freeze()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) { | pub fn set_content_length_if_missing(headers: &mut HeaderMap, len: u64) { | ||||||
|     headers |     headers | ||||||
|         .entry(CONTENT_LENGTH) |         .entry(CONTENT_LENGTH) | ||||||
|         .unwrap() |         .unwrap() | ||||||
|         .or_insert(content_length_value(len)); |         .or_insert_with(|| HeaderValue::from(len)); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn transfer_encoding_is_chunked(headers: &HeaderMap) -> bool { | pub fn transfer_encoding_is_chunked(headers: &HeaderMap) -> bool { | ||||||
| @@ -156,46 +123,3 @@ fn eq_ascii(left: &str, right: &str) -> bool { | |||||||
|  |  | ||||||
|     left.eq_ignore_ascii_case(right) |     left.eq_ignore_ascii_case(right) | ||||||
| } | } | ||||||
|  |  | ||||||
| #[cfg(test)] |  | ||||||
| mod tests { |  | ||||||
|  |  | ||||||
|     #[cfg(feature = "nightly")] |  | ||||||
|     use test::Bencher; |  | ||||||
|  |  | ||||||
|     #[test] |  | ||||||
|     fn assert_max_decimal_u64_bytes() { |  | ||||||
|         assert_eq!( |  | ||||||
|             super::MAX_DECIMAL_U64_BYTES, |  | ||||||
|             ::std::u64::MAX.to_string().len() |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     #[cfg(feature = "nightly")] |  | ||||||
|     #[bench] |  | ||||||
|     fn bench_content_length_fmt_small(b: &mut Bencher) { |  | ||||||
|         let n = 13; |  | ||||||
|         let s = n.to_string(); |  | ||||||
|         b.bytes = s.len() as u64; |  | ||||||
|  |  | ||||||
|         b.iter(|| { |  | ||||||
|             let val = super::content_length_value(n); |  | ||||||
|             debug_assert_eq!(val, s); |  | ||||||
|             ::test::black_box(&val); |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     #[cfg(feature = "nightly")] |  | ||||||
|     #[bench] |  | ||||||
|     fn bench_content_length_fmt_big(b: &mut Bencher) { |  | ||||||
|         let n = 326_893_010; |  | ||||||
|         let s = n.to_string(); |  | ||||||
|         b.bytes = s.len() as u64; |  | ||||||
|  |  | ||||||
|         b.iter(|| { |  | ||||||
|             let val = super::content_length_value(n); |  | ||||||
|             debug_assert_eq!(val, s); |  | ||||||
|             ::test::black_box(&val); |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -842,16 +842,16 @@ fn set_content_length(headers: &mut HeaderMap, len: u64) -> Encoder { | |||||||
|                 // with our known good length. |                 // with our known good length. | ||||||
|                 error!("user provided content-length header was invalid"); |                 error!("user provided content-length header was invalid"); | ||||||
|  |  | ||||||
|                 cl.insert(headers::content_length_value(len)); |                 cl.insert(HeaderValue::from(len)); | ||||||
|                 Encoder::length(len) |                 Encoder::length(len) | ||||||
|             }, |             }, | ||||||
|             Entry::Vacant(cl) => { |             Entry::Vacant(cl) => { | ||||||
|                 cl.insert(headers::content_length_value(len)); |                 cl.insert(HeaderValue::from(len)); | ||||||
|                 Encoder::length(len) |                 Encoder::length(len) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         headers.insert(header::CONTENT_LENGTH, headers::content_length_value(len)); |         headers.insert(header::CONTENT_LENGTH, HeaderValue::from(len)); | ||||||
|         Encoder::length(len) |         Encoder::length(len) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user