Skip to main content

ContentEncoding

Struct ContentEncoding 

Source
pub struct ContentEncoding { /* private fields */ }
Expand description

The codings a response says its body carries.

Read from every Content-Encoding line together: a representation encoded more than once may arrive comma-joined on one line or split across several, and it is the same list either way.

Implementations§

Source§

impl ContentEncoding

Source

pub fn codings(&self) -> &[Coding]

The codings the header carried, in the order it applied them.

Empty for a response that declared none, and for one whose header could not be read.

Source

pub fn layer(&self, coding: Coding) -> Self

Add a coding on top of the ones already here.

Applied last, so it is last in the header: the codings are listed in the order they were applied, and a reader unwinds them in reverse.

Examples found in repository?
examples/codings.rs (line 53)
16async fn main() {
17	let accept = AcceptEncoding::from(DEFAULT_ACCEPT_ENCODING);
18
19	let mut headers = HeaderMap::new();
20	headers.insert("content-encoding", HeaderValue::from_static("gzip"));
21	headers.insert("content-length", HeaderValue::from_static("42"));
22	// Just the header half, so the coding is in hand for the round trip below; `response::decode`
23	// does this and the body together.
24	let coding = ContentEncoding::peel_one_header(&mut headers, &accept)
25		.expect("gzip is in the default Accept-Encoding");
26	println!("negotiated: {coding:?}");
27	println!("headers after decoding: {:?}", headers.keys().count());
28
29	// Round-trip a body through the coding that was negotiated.
30	let original = b"the quick brown fox jumps over the lazy dog".repeat(8);
31	let compressed = compress_buffer(&original, coding.clone())
32		.await
33		.expect("gzip compresses");
34	println!(
35		"{} bytes in, {} bytes out",
36		original.len(),
37		compressed.len()
38	);
39
40	let stream = futures::stream::once(async move { Ok(Bytes::from(compressed)) });
41	let mut decoded = decode_stream(Box::pin(stream), coding);
42	let mut round_tripped = Vec::new();
43	while let Some(chunk) = decoded.next().await {
44		round_tripped.extend_from_slice(&chunk.expect("the body decodes"));
45	}
46	println!("round-tripped intact: {}", round_tripped == original);
47
48	// Compressing a request on top of a coding the caller already applied declares both, in the
49	// order they were applied.
50	let mut request = HeaderMap::new();
51	request.insert("content-encoding", HeaderValue::from_static("br"));
52
53	let layered = ContentEncoding::from(&request).layer(Coding::Gzip);
54	if let Some(value) = layered.to_header_value() {
55		request.insert("content-encoding", value);
56	}
57	println!(
58		"Content-Encoding: {}",
59		request["content-encoding"].to_str().unwrap()
60	);
61}
Source

pub fn to_header_value(&self) -> Option<HeaderValue>

The header value these codings make, or None when there are none to declare.

Examples found in repository?
examples/codings.rs (line 54)
16async fn main() {
17	let accept = AcceptEncoding::from(DEFAULT_ACCEPT_ENCODING);
18
19	let mut headers = HeaderMap::new();
20	headers.insert("content-encoding", HeaderValue::from_static("gzip"));
21	headers.insert("content-length", HeaderValue::from_static("42"));
22	// Just the header half, so the coding is in hand for the round trip below; `response::decode`
23	// does this and the body together.
24	let coding = ContentEncoding::peel_one_header(&mut headers, &accept)
25		.expect("gzip is in the default Accept-Encoding");
26	println!("negotiated: {coding:?}");
27	println!("headers after decoding: {:?}", headers.keys().count());
28
29	// Round-trip a body through the coding that was negotiated.
30	let original = b"the quick brown fox jumps over the lazy dog".repeat(8);
31	let compressed = compress_buffer(&original, coding.clone())
32		.await
33		.expect("gzip compresses");
34	println!(
35		"{} bytes in, {} bytes out",
36		original.len(),
37		compressed.len()
38	);
39
40	let stream = futures::stream::once(async move { Ok(Bytes::from(compressed)) });
41	let mut decoded = decode_stream(Box::pin(stream), coding);
42	let mut round_tripped = Vec::new();
43	while let Some(chunk) = decoded.next().await {
44		round_tripped.extend_from_slice(&chunk.expect("the body decodes"));
45	}
46	println!("round-tripped intact: {}", round_tripped == original);
47
48	// Compressing a request on top of a coding the caller already applied declares both, in the
49	// order they were applied.
50	let mut request = HeaderMap::new();
51	request.insert("content-encoding", HeaderValue::from_static("br"));
52
53	let layered = ContentEncoding::from(&request).layer(Coding::Gzip);
54	if let Some(value) = layered.to_header_value() {
55		request.insert("content-encoding", value);
56	}
57	println!(
58		"Content-Encoding: {}",
59		request["content-encoding"].to_str().unwrap()
60	);
61}
Source

pub fn can_decode_as(&self, accept: &AcceptEncoding) -> Option<Coding>

The coding the next layer of the body is under, given what the request accepted.

The last coding, being the last applied and so the first to unwind. None leaves the body as it arrived, which covers a response that declared no coding, one whose outermost coding this crate cannot decode (identity among them) or the request did not accept, and one whose header was not readable.

Source

pub fn peeled(&self) -> Self

These codings with the outermost removed, as the body stands once it is decoded.

Source

pub fn peel_one_header( headers: &mut HeaderMap, accept: &AcceptEncoding, ) -> Option<Coding>

Take one layer off headers, returning the coding its body is under.

The headers are left describing the body once that coding has been decoded, which response::decode does in the same call. Reach for this only to drive the two halves separately.

Content-Encoding keeps whatever layers remain and goes when none do; Content-Length goes either way, no longer describing what the caller reads. None leaves headers as they are.

Examples found in repository?
examples/codings.rs (line 24)
16async fn main() {
17	let accept = AcceptEncoding::from(DEFAULT_ACCEPT_ENCODING);
18
19	let mut headers = HeaderMap::new();
20	headers.insert("content-encoding", HeaderValue::from_static("gzip"));
21	headers.insert("content-length", HeaderValue::from_static("42"));
22	// Just the header half, so the coding is in hand for the round trip below; `response::decode`
23	// does this and the body together.
24	let coding = ContentEncoding::peel_one_header(&mut headers, &accept)
25		.expect("gzip is in the default Accept-Encoding");
26	println!("negotiated: {coding:?}");
27	println!("headers after decoding: {:?}", headers.keys().count());
28
29	// Round-trip a body through the coding that was negotiated.
30	let original = b"the quick brown fox jumps over the lazy dog".repeat(8);
31	let compressed = compress_buffer(&original, coding.clone())
32		.await
33		.expect("gzip compresses");
34	println!(
35		"{} bytes in, {} bytes out",
36		original.len(),
37		compressed.len()
38	);
39
40	let stream = futures::stream::once(async move { Ok(Bytes::from(compressed)) });
41	let mut decoded = decode_stream(Box::pin(stream), coding);
42	let mut round_tripped = Vec::new();
43	while let Some(chunk) = decoded.next().await {
44		round_tripped.extend_from_slice(&chunk.expect("the body decodes"));
45	}
46	println!("round-tripped intact: {}", round_tripped == original);
47
48	// Compressing a request on top of a coding the caller already applied declares both, in the
49	// order they were applied.
50	let mut request = HeaderMap::new();
51	request.insert("content-encoding", HeaderValue::from_static("br"));
52
53	let layered = ContentEncoding::from(&request).layer(Coding::Gzip);
54	if let Some(value) = layered.to_header_value() {
55		request.insert("content-encoding", value);
56	}
57	println!(
58		"Content-Encoding: {}",
59		request["content-encoding"].to_str().unwrap()
60	);
61}

Trait Implementations§

Source§

impl Clone for ContentEncoding

Source§

fn clone(&self) -> ContentEncoding

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ContentEncoding

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ContentEncoding

Source§

fn default() -> ContentEncoding

Returns the “default value” for a type. Read more
Source§

impl Display for ContentEncoding

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<&HeaderMap> for ContentEncoding

Source§

fn from(headers: &HeaderMap) -> Self

Converts to this type from the input type.
Source§

impl From<&str> for ContentEncoding

Source§

fn from(value: &str) -> Self

Read one Content-Encoding header value.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.