1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-25 00:12:59 +01:00
actix-extras/src/message.rs

249 lines
5.9 KiB
Rust
Raw Normal View History

2019-02-08 06:16:46 +01:00
use std::cell::{Ref, RefCell, RefMut};
2018-11-17 04:28:07 +01:00
use std::collections::VecDeque;
use std::rc::Rc;
use http::{HeaderMap, Method, StatusCode, Uri, Version};
2018-12-06 23:32:52 +01:00
use crate::extensions::Extensions;
2018-11-17 04:28:07 +01:00
/// Represents various types of connection
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ConnectionType {
/// Close connection after response
Close,
/// Keep connection alive after response
KeepAlive,
/// Connection is upgraded to different type
Upgrade,
}
2018-11-17 04:28:07 +01:00
#[doc(hidden)]
pub trait Head: Default + 'static {
fn clear(&mut self);
/// Connection type
fn connection_type(&self) -> ConnectionType;
2018-11-19 02:52:56 +01:00
/// Set connection type of the message
fn set_connection_type(&mut self, ctype: ConnectionType);
2018-11-19 02:52:56 +01:00
fn upgrade(&self) -> bool {
self.connection_type() == ConnectionType::Upgrade
2018-11-19 02:52:56 +01:00
}
fn keep_alive(&self) -> bool {
self.connection_type() == ConnectionType::KeepAlive
2018-11-19 02:52:56 +01:00
}
fn pool() -> &'static MessagePool<Self>;
2018-11-17 04:28:07 +01:00
}
2018-11-19 23:57:12 +01:00
#[derive(Debug)]
2018-11-17 04:28:07 +01:00
pub struct RequestHead {
pub uri: Uri,
pub method: Method,
pub version: Version,
pub headers: HeaderMap,
2018-11-19 23:57:12 +01:00
pub ctype: Option<ConnectionType>,
2019-02-09 19:33:49 +01:00
pub extensions: RefCell<Extensions>,
2018-11-17 04:28:07 +01:00
}
impl Default for RequestHead {
fn default() -> RequestHead {
RequestHead {
uri: Uri::default(),
method: Method::default(),
version: Version::HTTP_11,
headers: HeaderMap::with_capacity(16),
ctype: None,
2019-02-09 19:33:49 +01:00
extensions: RefCell::new(Extensions::new()),
2018-11-17 04:28:07 +01:00
}
}
}
impl Head for RequestHead {
fn clear(&mut self) {
self.ctype = None;
2018-11-17 04:28:07 +01:00
self.headers.clear();
2019-02-09 19:33:49 +01:00
self.extensions.borrow_mut().clear();
2018-11-19 02:52:56 +01:00
}
fn set_connection_type(&mut self, ctype: ConnectionType) {
self.ctype = Some(ctype)
2018-11-19 02:52:56 +01:00
}
fn connection_type(&self) -> ConnectionType {
if let Some(ct) = self.ctype {
ct
2018-11-19 23:57:12 +01:00
} else if self.version < Version::HTTP_11 {
ConnectionType::Close
2018-11-19 02:52:56 +01:00
} else {
ConnectionType::KeepAlive
2018-11-19 02:52:56 +01:00
}
}
2018-11-17 04:28:07 +01:00
fn pool() -> &'static MessagePool<Self> {
REQUEST_POOL.with(|p| *p)
}
}
2019-02-09 19:33:49 +01:00
impl RequestHead {
/// Message extensions
#[inline]
pub fn extensions(&self) -> Ref<Extensions> {
self.extensions.borrow()
}
/// Mutable reference to a the message's extensions
#[inline]
pub fn extensions_mut(&self) -> RefMut<Extensions> {
self.extensions.borrow_mut()
}
}
2018-11-19 23:57:12 +01:00
#[derive(Debug)]
2018-11-17 04:28:07 +01:00
pub struct ResponseHead {
pub version: Version,
2018-11-17 04:28:07 +01:00
pub status: StatusCode,
pub headers: HeaderMap,
pub reason: Option<&'static str>,
pub(crate) ctype: Option<ConnectionType>,
2018-11-17 04:28:07 +01:00
}
impl Default for ResponseHead {
fn default() -> ResponseHead {
ResponseHead {
version: Version::default(),
2018-11-17 04:28:07 +01:00
status: StatusCode::OK,
headers: HeaderMap::with_capacity(16),
reason: None,
ctype: None,
2018-11-17 04:28:07 +01:00
}
}
}
impl Head for ResponseHead {
fn clear(&mut self) {
self.ctype = None;
2018-11-17 17:56:40 +01:00
self.reason = None;
2018-11-17 04:28:07 +01:00
self.headers.clear();
2018-11-19 02:52:56 +01:00
}
fn set_connection_type(&mut self, ctype: ConnectionType) {
self.ctype = Some(ctype)
2018-11-19 02:52:56 +01:00
}
fn connection_type(&self) -> ConnectionType {
if let Some(ct) = self.ctype {
ct
2018-11-19 23:57:12 +01:00
} else if self.version < Version::HTTP_11 {
ConnectionType::Close
2018-11-19 02:52:56 +01:00
} else {
ConnectionType::KeepAlive
2018-11-19 02:52:56 +01:00
}
}
2018-11-17 04:28:07 +01:00
fn pool() -> &'static MessagePool<Self> {
RESPONSE_POOL.with(|p| *p)
}
}
2018-11-19 02:52:56 +01:00
impl ResponseHead {
/// Get custom reason for the response
#[inline]
pub fn reason(&self) -> &str {
if let Some(reason) = self.reason {
reason
} else {
self.status
.canonical_reason()
.unwrap_or("<unknown status code>")
}
}
}
2018-11-17 04:28:07 +01:00
pub struct Message<T: Head> {
2019-02-09 19:33:49 +01:00
head: Rc<T>,
2019-02-08 06:16:46 +01:00
pool: &'static MessagePool<T>,
2018-11-17 04:28:07 +01:00
}
impl<T: Head> Message<T> {
2019-02-08 06:16:46 +01:00
/// Get new message from the pool of objects
pub fn new() -> Self {
T::pool().get_message()
}
}
impl<T: Head> Clone for Message<T> {
fn clone(&self) -> Self {
Message {
2019-02-09 19:33:49 +01:00
head: self.head.clone(),
pool: self.pool,
}
}
}
2019-02-08 06:16:46 +01:00
impl<T: Head> std::ops::Deref for Message<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
2019-02-09 19:33:49 +01:00
&self.head.as_ref()
2019-02-08 06:16:46 +01:00
}
}
impl<T: Head> std::ops::DerefMut for Message<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
2019-02-09 19:33:49 +01:00
Rc::get_mut(&mut self.head).expect("Multiple copies exist")
2019-02-08 06:16:46 +01:00
}
}
impl<T: Head> Drop for Message<T> {
fn drop(&mut self) {
2019-02-09 19:33:49 +01:00
if Rc::strong_count(&self.head) == 1 {
self.pool.release(self.head.clone());
2018-11-17 04:28:07 +01:00
}
}
}
#[doc(hidden)]
/// Request's objects pool
2019-02-09 19:33:49 +01:00
pub struct MessagePool<T: Head>(RefCell<VecDeque<Rc<T>>>);
2018-11-17 04:28:07 +01:00
thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
thread_local!(static RESPONSE_POOL: &'static MessagePool<ResponseHead> = MessagePool::<ResponseHead>::create());
impl<T: Head> MessagePool<T> {
fn create() -> &'static MessagePool<T> {
let pool = MessagePool(RefCell::new(VecDeque::with_capacity(128)));
Box::leak(Box::new(pool))
}
2019-02-08 06:16:46 +01:00
/// Get message from the pool
#[inline]
fn get_message(&'static self) -> Message<T> {
if let Some(mut msg) = self.0.borrow_mut().pop_front() {
if let Some(r) = Rc::get_mut(&mut msg) {
2019-02-09 19:33:49 +01:00
r.clear();
2019-02-08 06:16:46 +01:00
}
Message {
2019-02-09 19:33:49 +01:00
head: msg,
2019-02-08 06:16:46 +01:00
pool: self,
}
} else {
Message {
2019-02-09 19:33:49 +01:00
head: Rc::new(T::default()),
2019-02-08 06:16:46 +01:00
pool: self,
}
}
}
2018-11-17 04:28:07 +01:00
#[inline]
/// Release request instance
2019-02-09 19:33:49 +01:00
fn release(&self, msg: Rc<T>) {
2018-11-17 04:28:07 +01:00
let v = &mut self.0.borrow_mut();
if v.len() < 128 {
v.push_front(msg);
}
}
}