summaryrefslogtreecommitdiffstats
path: root/third_party/rust/headers/src/common/content_length.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/headers/src/common/content_length.rs')
-rw-r--r--third_party/rust/headers/src/common/content_length.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/third_party/rust/headers/src/common/content_length.rs b/third_party/rust/headers/src/common/content_length.rs
new file mode 100644
index 0000000000..ff8c54234d
--- /dev/null
+++ b/third_party/rust/headers/src/common/content_length.rs
@@ -0,0 +1,95 @@
+use {Header, HeaderValue};
+
+/// `Content-Length` header, defined in
+/// [RFC7230](http://tools.ietf.org/html/rfc7230#section-3.3.2)
+///
+/// When a message does not have a `Transfer-Encoding` header field, a
+/// Content-Length header field can provide the anticipated size, as a
+/// decimal number of octets, for a potential payload body. For messages
+/// that do include a payload body, the Content-Length field-value
+/// provides the framing information necessary for determining where the
+/// body (and message) ends. For messages that do not include a payload
+/// body, the Content-Length indicates the size of the selected
+/// representation.
+///
+/// Note that setting this header will *remove* any previously set
+/// `Transfer-Encoding` header, in accordance with
+/// [RFC7230](http://tools.ietf.org/html/rfc7230#section-3.3.2):
+///
+/// > A sender MUST NOT send a Content-Length header field in any message
+/// > that contains a Transfer-Encoding header field.
+///
+/// ## ABNF
+///
+/// ```text
+/// Content-Length = 1*DIGIT
+/// ```
+///
+/// ## Example values
+///
+/// * `3495`
+///
+/// # Example
+///
+/// ```
+/// # extern crate headers;
+/// use headers::ContentLength;
+///
+/// let len = ContentLength(1_000);
+/// ```
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct ContentLength(pub u64);
+
+impl Header for ContentLength {
+ fn name() -> &'static ::http::header::HeaderName {
+ &::http::header::CONTENT_LENGTH
+ }
+
+ fn decode<'i, I: Iterator<Item = &'i HeaderValue>>(values: &mut I) -> Result<Self, ::Error> {
+ // If multiple Content-Length headers were sent, everything can still
+ // be alright if they all contain the same value, and all parse
+ // correctly. If not, then it's an error.
+ let mut len = None;
+ for value in values {
+ let parsed = value
+ .to_str()
+ .map_err(|_| ::Error::invalid())?
+ .parse::<u64>()
+ .map_err(|_| ::Error::invalid())?;
+
+ if let Some(prev) = len {
+ if prev != parsed {
+ return Err(::Error::invalid());
+ }
+ } else {
+ len = Some(parsed);
+ }
+ }
+
+ len.map(ContentLength).ok_or_else(::Error::invalid)
+ }
+
+ fn encode<E: Extend<::HeaderValue>>(&self, values: &mut E) {
+ values.extend(::std::iter::once(self.0.into()));
+ }
+}
+
+/*
+__hyper__tm!(ContentLength, tests {
+ // Testcase from RFC
+ test_header!(test1, vec![b"3495"], Some(HeaderField(3495)));
+
+ test_header!(test_invalid, vec![b"34v95"], None);
+
+ // Can't use the test_header macro because "5, 5" gets cleaned to "5".
+ #[test]
+ fn test_duplicates() {
+ let parsed = HeaderField::parse_header(&vec![b"5".to_vec(),
+ b"5".to_vec()].into()).unwrap();
+ assert_eq!(parsed, HeaderField(5));
+ assert_eq!(format!("{}", parsed), "5");
+ }
+
+ test_header!(test_duplicates_vary, vec![b"5", b"6", b"5"], None);
+});
+*/