http1_spec/
response_head_renderer.rs1use std::io::{Error as IoError, ErrorKind as IoErrorKind};
2
3use http::{response::Parts, Response, Version};
4
5use crate::{
6 head_renderer::HeadRenderer, ReasonPhrase, COLON, CRLF, HTTP_VERSION_10, HTTP_VERSION_11,
7 HTTP_VERSION_2, HTTP_VERSION_3, SP,
8};
9
10#[derive(Default)]
11pub struct ResponseHeadRenderer {}
12
13impl HeadRenderer<(Response<()>, ReasonPhrase)> for ResponseHeadRenderer {
14 fn new() -> Self {
15 Self::default()
16 }
17
18 fn render(&self, head: (Response<()>, ReasonPhrase), buf: &mut Vec<u8>) -> Result<(), IoError> {
19 let (head, reason_phrase) = head;
20
21 let (parts, _) = head.into_parts();
22 HeadRenderer::<(Parts, ReasonPhrase)>::render(self, (parts, reason_phrase), buf)
23 }
24}
25
26impl HeadRenderer<(Parts, ReasonPhrase)> for ResponseHeadRenderer {
27 fn new() -> Self {
28 Self::default()
29 }
30
31 fn render(&self, head: (Parts, ReasonPhrase), buf: &mut Vec<u8>) -> Result<(), IoError> {
32 let (parts, reason_phrase) = head;
33
34 let version_bytes = match parts.version {
35 Version::HTTP_10 => HTTP_VERSION_10,
36 Version::HTTP_11 => HTTP_VERSION_11,
37 Version::HTTP_2 => HTTP_VERSION_2,
38 Version::HTTP_3 => HTTP_VERSION_3,
39 _ => return Err(IoError::new(IoErrorKind::InvalidInput, "unimplemented")),
40 };
41
42 buf.extend_from_slice(version_bytes);
43 buf.extend_from_slice(&[SP]);
44 buf.extend_from_slice(parts.status.as_str().as_bytes());
45 buf.extend_from_slice(&[SP]);
46 if let Some(reason_phrase) = reason_phrase.or_else(|| {
47 parts
48 .status
49 .canonical_reason()
50 .map(|x| x.as_bytes().to_vec())
51 }) {
52 buf.extend_from_slice(&reason_phrase[..]);
53 }
54 buf.extend_from_slice(CRLF);
55
56 for (k, v) in &parts.headers {
57 buf.extend_from_slice(k.to_string().as_bytes());
58 buf.extend_from_slice(&[COLON]);
59 buf.extend_from_slice(v.as_bytes());
60 buf.extend_from_slice(CRLF);
61 }
62
63 buf.extend_from_slice(CRLF);
64
65 Ok(())
66 }
67}