1use std::cell::{Ref, RefCell, RefMut};
2use std::net;
3use std::rc::Rc;
4
5use bitflags::bitflags;
6use copyless::BoxHelper;
7
8use crate::extensions::Extensions;
9use crate::header::HeaderMap;
10use crate::http::{header, Method, StatusCode, Uri, Version};
11
12#[derive(Copy, Clone, PartialEq, Debug)]
14pub enum ConnectionType {
15 Close,
17 KeepAlive,
19 Upgrade,
21}
22
23bitflags! {
24 pub(crate) struct Flags: u8 {
25 const CLOSE = 0b0000_0001;
26 const KEEP_ALIVE = 0b0000_0010;
27 const UPGRADE = 0b0000_0100;
28 const EXPECT = 0b0000_1000;
29 const NO_CHUNKING = 0b0001_0000;
30 const CAMEL_CASE = 0b0010_0000;
31 }
32}
33
34#[doc(hidden)]
35pub trait Head: Default + 'static {
36 fn clear(&mut self);
37
38 fn pool() -> &'static MessagePool<Self>;
39}
40
41#[derive(Debug)]
42pub struct RequestHead {
43 pub uri: Uri,
44 pub method: Method,
45 pub version: Version,
46 pub headers: HeaderMap,
47 pub extensions: RefCell<Extensions>,
48 pub peer_addr: Option<net::SocketAddr>,
49 flags: Flags,
50}
51
52impl Default for RequestHead {
53 fn default() -> RequestHead {
54 RequestHead {
55 uri: Uri::default(),
56 method: Method::default(),
57 version: Version::HTTP_11,
58 headers: HeaderMap::with_capacity(16),
59 flags: Flags::empty(),
60 peer_addr: None,
61 extensions: RefCell::new(Extensions::new()),
62 }
63 }
64}
65
66impl Head for RequestHead {
67 fn clear(&mut self) {
68 self.flags = Flags::empty();
69 self.headers.clear();
70 self.extensions.borrow_mut().clear();
71 }
72
73 fn pool() -> &'static MessagePool<Self> {
74 REQUEST_POOL.with(|p| *p)
75 }
76}
77
78impl RequestHead {
79 #[inline]
81 pub fn extensions(&self) -> Ref<'_, Extensions> {
82 self.extensions.borrow()
83 }
84
85 #[inline]
87 pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
88 self.extensions.borrow_mut()
89 }
90
91 pub fn headers(&self) -> &HeaderMap {
93 &self.headers
94 }
95
96 pub fn headers_mut(&mut self) -> &mut HeaderMap {
98 &mut self.headers
99 }
100
101 #[inline]
104 pub fn camel_case_headers(&self) -> bool {
105 self.flags.contains(Flags::CAMEL_CASE)
106 }
107
108 #[inline]
110 pub fn set_camel_case_headers(&mut self, val: bool) {
111 if val {
112 self.flags.insert(Flags::CAMEL_CASE);
113 } else {
114 self.flags.remove(Flags::CAMEL_CASE);
115 }
116 }
117
118 #[inline]
119 pub fn set_connection_type(&mut self, ctype: ConnectionType) {
121 match ctype {
122 ConnectionType::Close => self.flags.insert(Flags::CLOSE),
123 ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
124 ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
125 }
126 }
127
128 #[inline]
129 pub fn connection_type(&self) -> ConnectionType {
131 if self.flags.contains(Flags::CLOSE) {
132 ConnectionType::Close
133 } else if self.flags.contains(Flags::KEEP_ALIVE) {
134 ConnectionType::KeepAlive
135 } else if self.flags.contains(Flags::UPGRADE) {
136 ConnectionType::Upgrade
137 } else if self.version < Version::HTTP_11 {
138 ConnectionType::Close
139 } else {
140 ConnectionType::KeepAlive
141 }
142 }
143
144 pub fn upgrade(&self) -> bool {
146 if let Some(hdr) = self.headers().get(header::CONNECTION) {
147 if let Ok(s) = hdr.to_str() {
148 s.to_ascii_lowercase().contains("upgrade")
149 } else {
150 false
151 }
152 } else {
153 false
154 }
155 }
156
157 #[inline]
158 pub fn chunked(&self) -> bool {
160 !self.flags.contains(Flags::NO_CHUNKING)
161 }
162
163 #[inline]
164 pub fn no_chunking(&mut self, val: bool) {
165 if val {
166 self.flags.insert(Flags::NO_CHUNKING);
167 } else {
168 self.flags.remove(Flags::NO_CHUNKING);
169 }
170 }
171
172 #[inline]
173 pub fn expect(&self) -> bool {
175 self.flags.contains(Flags::EXPECT)
176 }
177
178 #[inline]
179 pub(crate) fn set_expect(&mut self) {
180 self.flags.insert(Flags::EXPECT);
181 }
182}
183
184#[derive(Debug)]
185pub enum RequestHeadType {
186 Owned(RequestHead),
187 Rc(Rc<RequestHead>, Option<HeaderMap>),
188}
189
190impl RequestHeadType {
191 pub fn extra_headers(&self) -> Option<&HeaderMap> {
192 match self {
193 RequestHeadType::Owned(_) => None,
194 RequestHeadType::Rc(_, headers) => headers.as_ref(),
195 }
196 }
197}
198
199impl AsRef<RequestHead> for RequestHeadType {
200 fn as_ref(&self) -> &RequestHead {
201 match self {
202 RequestHeadType::Owned(head) => &head,
203 RequestHeadType::Rc(head, _) => head.as_ref(),
204 }
205 }
206}
207
208impl From<RequestHead> for RequestHeadType {
209 fn from(head: RequestHead) -> Self {
210 RequestHeadType::Owned(head)
211 }
212}
213
214#[derive(Debug)]
215pub struct ResponseHead {
216 pub version: Version,
217 pub status: StatusCode,
218 pub headers: HeaderMap,
219 pub reason: Option<&'static str>,
220 pub(crate) extensions: RefCell<Extensions>,
221 flags: Flags,
222}
223
224impl ResponseHead {
225 #[inline]
227 pub fn new(status: StatusCode) -> ResponseHead {
228 ResponseHead {
229 status,
230 version: Version::default(),
231 headers: HeaderMap::with_capacity(12),
232 reason: None,
233 flags: Flags::empty(),
234 extensions: RefCell::new(Extensions::new()),
235 }
236 }
237
238 #[inline]
240 pub fn extensions(&self) -> Ref<'_, Extensions> {
241 self.extensions.borrow()
242 }
243
244 #[inline]
246 pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
247 self.extensions.borrow_mut()
248 }
249
250 #[inline]
251 pub fn headers(&self) -> &HeaderMap {
253 &self.headers
254 }
255
256 #[inline]
257 pub fn headers_mut(&mut self) -> &mut HeaderMap {
259 &mut self.headers
260 }
261
262 #[inline]
263 pub fn set_connection_type(&mut self, ctype: ConnectionType) {
265 match ctype {
266 ConnectionType::Close => self.flags.insert(Flags::CLOSE),
267 ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
268 ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
269 }
270 }
271
272 #[inline]
273 pub fn connection_type(&self) -> ConnectionType {
274 if self.flags.contains(Flags::CLOSE) {
275 ConnectionType::Close
276 } else if self.flags.contains(Flags::KEEP_ALIVE) {
277 ConnectionType::KeepAlive
278 } else if self.flags.contains(Flags::UPGRADE) {
279 ConnectionType::Upgrade
280 } else if self.version < Version::HTTP_11 {
281 ConnectionType::Close
282 } else {
283 ConnectionType::KeepAlive
284 }
285 }
286
287 #[inline]
288 pub fn keep_alive(&self) -> bool {
290 self.connection_type() == ConnectionType::KeepAlive
291 }
292
293 #[inline]
294 pub fn upgrade(&self) -> bool {
296 self.connection_type() == ConnectionType::Upgrade
297 }
298
299 #[inline]
301 pub fn reason(&self) -> &str {
302 if let Some(reason) = self.reason {
303 reason
304 } else {
305 self.status
306 .canonical_reason()
307 .unwrap_or("<unknown status code>")
308 }
309 }
310
311 #[inline]
312 pub(crate) fn ctype(&self) -> Option<ConnectionType> {
313 if self.flags.contains(Flags::CLOSE) {
314 Some(ConnectionType::Close)
315 } else if self.flags.contains(Flags::KEEP_ALIVE) {
316 Some(ConnectionType::KeepAlive)
317 } else if self.flags.contains(Flags::UPGRADE) {
318 Some(ConnectionType::Upgrade)
319 } else {
320 None
321 }
322 }
323
324 #[inline]
325 pub fn chunked(&self) -> bool {
327 !self.flags.contains(Flags::NO_CHUNKING)
328 }
329
330 #[inline]
331 pub fn no_chunking(&mut self, val: bool) {
333 if val {
334 self.flags.insert(Flags::NO_CHUNKING);
335 } else {
336 self.flags.remove(Flags::NO_CHUNKING);
337 }
338 }
339}
340
341pub struct Message<T: Head> {
342 head: Rc<T>,
343}
344
345impl<T: Head> Message<T> {
346 pub fn new() -> Self {
348 T::pool().get_message()
349 }
350}
351
352impl<T: Head> Clone for Message<T> {
353 fn clone(&self) -> Self {
354 Message {
355 head: self.head.clone(),
356 }
357 }
358}
359
360impl<T: Head> std::ops::Deref for Message<T> {
361 type Target = T;
362
363 fn deref(&self) -> &Self::Target {
364 &self.head.as_ref()
365 }
366}
367
368impl<T: Head> std::ops::DerefMut for Message<T> {
369 fn deref_mut(&mut self) -> &mut Self::Target {
370 Rc::get_mut(&mut self.head).expect("Multiple copies exist")
371 }
372}
373
374impl<T: Head> Drop for Message<T> {
375 fn drop(&mut self) {
376 if Rc::strong_count(&self.head) == 1 {
377 T::pool().release(self.head.clone());
378 }
379 }
380}
381
382pub(crate) struct BoxedResponseHead {
383 head: Option<Box<ResponseHead>>,
384}
385
386impl BoxedResponseHead {
387 pub fn new(status: StatusCode) -> Self {
389 RESPONSE_POOL.with(|p| p.get_message(status))
390 }
391
392 pub(crate) fn take(&mut self) -> Self {
393 BoxedResponseHead {
394 head: self.head.take(),
395 }
396 }
397}
398
399impl std::ops::Deref for BoxedResponseHead {
400 type Target = ResponseHead;
401
402 fn deref(&self) -> &Self::Target {
403 self.head.as_ref().unwrap()
404 }
405}
406
407impl std::ops::DerefMut for BoxedResponseHead {
408 fn deref_mut(&mut self) -> &mut Self::Target {
409 self.head.as_mut().unwrap()
410 }
411}
412
413impl Drop for BoxedResponseHead {
414 fn drop(&mut self) {
415 if let Some(head) = self.head.take() {
416 RESPONSE_POOL.with(move |p| p.release(head))
417 }
418 }
419}
420
421#[doc(hidden)]
422pub struct MessagePool<T: Head>(RefCell<Vec<Rc<T>>>);
424
425#[doc(hidden)]
426#[allow(clippy::vec_box)]
427pub struct BoxedResponsePool(RefCell<Vec<Box<ResponseHead>>>);
429
430thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
431thread_local!(static RESPONSE_POOL: &'static BoxedResponsePool = BoxedResponsePool::create());
432
433impl<T: Head> MessagePool<T> {
434 fn create() -> &'static MessagePool<T> {
435 let pool = MessagePool(RefCell::new(Vec::with_capacity(128)));
436 Box::leak(Box::new(pool))
437 }
438
439 #[inline]
441 fn get_message(&'static self) -> Message<T> {
442 if let Some(mut msg) = self.0.borrow_mut().pop() {
443 if let Some(r) = Rc::get_mut(&mut msg) {
444 r.clear();
445 }
446 Message { head: msg }
447 } else {
448 Message {
449 head: Rc::new(T::default()),
450 }
451 }
452 }
453
454 #[inline]
455 fn release(&self, msg: Rc<T>) {
457 let v = &mut self.0.borrow_mut();
458 if v.len() < 128 {
459 v.push(msg);
460 }
461 }
462}
463
464impl BoxedResponsePool {
465 fn create() -> &'static BoxedResponsePool {
466 let pool = BoxedResponsePool(RefCell::new(Vec::with_capacity(128)));
467 Box::leak(Box::new(pool))
468 }
469
470 #[inline]
472 fn get_message(&'static self, status: StatusCode) -> BoxedResponseHead {
473 if let Some(mut head) = self.0.borrow_mut().pop() {
474 head.reason = None;
475 head.status = status;
476 head.headers.clear();
477 head.flags = Flags::empty();
478 BoxedResponseHead { head: Some(head) }
479 } else {
480 BoxedResponseHead {
481 head: Some(Box::alloc().init(ResponseHead::new(status))),
482 }
483 }
484 }
485
486 #[inline]
487 fn release(&self, msg: Box<ResponseHead>) {
489 let v = &mut self.0.borrow_mut();
490 if v.len() < 128 {
491 msg.extensions.borrow_mut().clear();
492 v.push(msg);
493 }
494 }
495}