Skip to main content

sark_core/http/response/direct/
plan.rs

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