Skip to main content

sark_core/http/response/direct/
plan.rs

1use http::StatusCode;
2use o3::buffer::{Borrowed, Bytes, Owned, Retained, Shared};
3
4use super::super::{Body, HotBodyInner, HotHeadInner, MonoResponseInner, TextBody};
5use super::head::HeadInner;
6use super::headers::{HeaderNameToken, HeaderStaticValueToken, Headers};
7use super::value::InlineHeaderValue;
8
9#[derive(Clone, Debug)]
10pub struct ResponsePlan<'req> {
11    pub(in crate::http::response) status: StatusCode,
12    pub(in crate::http::response) head: HeadInner<'req>,
13}
14
15impl<'req> ResponsePlan<'req> {
16    pub fn with_capacity(status: StatusCode) -> Self {
17        Self {
18            status,
19            head: HeadInner::new(b"", Headers::new()),
20        }
21    }
22
23    pub fn from_static(status: StatusCode, static_headers: &'static [u8]) -> Self {
24        Self {
25            status,
26            head: HeadInner::new(static_headers, Headers::new()),
27        }
28    }
29
30    pub fn new(status: StatusCode) -> Self {
31        Self::with_capacity(status)
32    }
33
34    pub fn ok() -> Self {
35        Self::new(StatusCode::OK)
36    }
37
38    pub fn not_found() -> Self {
39        Self::new(StatusCode::NOT_FOUND)
40    }
41
42    pub fn status(&self) -> StatusCode {
43        self.status
44    }
45
46    pub fn wire_headers(&self) -> Shared {
47        let mut out = Owned::with_capacity(self.head.wire_len());
48        self.head.write_into_owned(&mut out);
49        out.freeze()
50    }
51
52    pub fn push_static(&mut self, name: &'static str, value: &'static str) -> &mut Self {
53        let name = HeaderNameToken::new(name);
54        let value = HeaderStaticValueToken::new(value);
55        self.head.headers_mut().push_static(name, value);
56        self
57    }
58
59    pub fn push(&mut self, name: &'static str, value: &str) -> &mut Self {
60        self.push_str_value(HeaderNameToken::new(name), value)
61    }
62
63    pub fn push_token_static(
64        &mut self,
65        name: HeaderNameToken,
66        value: HeaderStaticValueToken,
67    ) -> &mut Self {
68        self.head.headers_mut().push_static(name, value);
69        self
70    }
71
72    pub fn push_token(&mut self, name: HeaderNameToken, value: &str) -> &mut Self {
73        self.push_str_value(name, value)
74    }
75
76    fn push_str_value(&mut self, name: HeaderNameToken, value: &str) -> &mut Self {
77        HeaderStaticValueToken::validate(value);
78        if value.len() <= 31 {
79            self.head
80                .headers_mut()
81                .push_inline(name, InlineHeaderValue::new(value.as_bytes()));
82        } else {
83            self.head
84                .headers_mut()
85                .push_shared(name, Shared::copy_from_slice(value.as_bytes()));
86        }
87        self
88    }
89
90    pub fn push_borrowed_token(
91        &mut self,
92        name: HeaderNameToken,
93        value: Bytes<Borrowed<'req>>,
94    ) -> &mut Self {
95        HeaderStaticValueToken::validate_bytes(value.as_slice());
96        self.head.headers_mut().push_borrowed(name, value);
97        self
98    }
99
100    pub fn push_retained_token(
101        &mut self,
102        name: HeaderNameToken,
103        value: Bytes<Retained>,
104    ) -> &mut Self {
105        HeaderStaticValueToken::validate_bytes(value.as_slice());
106        self.head.headers_mut().push_retained(name, value);
107        self
108    }
109
110    pub fn respond_mono<B>(self, body: B) -> MonoResponseInner<'req>
111    where
112        B: Into<Body<'req>>,
113    {
114        let status = self.status;
115        MonoResponseInner {
116            status,
117            headers: None,
118            head: HotHeadInner::Direct(self.head),
119            body: HotBodyInner::from(body.into()),
120        }
121    }
122
123    pub fn respond_text<T>(self, body: T) -> MonoResponseInner<'req>
124    where
125        T: Into<TextBody<'req>>,
126    {
127        let status = self.status;
128        MonoResponseInner {
129            status,
130            headers: None,
131            head: HotHeadInner::Direct(self.head),
132            body: HotBodyInner::Text(body.into()),
133        }
134    }
135}