pub(crate) mod client_addr;
mod data;
mod from_state;
mod request_id;
use bytes::Bytes;
use http::{request, Request};
use http_body::Body as HttpBody;
use http_body_util::combinators::UnsyncBoxBody;
use http_body_util::BodyExt as _;
use hyper::upgrade::OnUpgrade;
use log::{debug, trace};
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::hash::{BuildHasherDefault, Hasher};
use std::io;
use std::net::SocketAddr;
pub use crate::state::client_addr::client_addr;
pub use crate::state::data::StateData;
pub use crate::state::from_state::FromState;
pub use crate::state::request_id::request_id;
use crate::helpers::http::request::path::RequestPathSegments;
use crate::state::client_addr::put_client_addr;
pub(crate) use crate::state::request_id::set_request_id;
#[derive(Default)]
struct IdHasher(u64);
impl Hasher for IdHasher {
fn write(&mut self, _: &[u8]) {
unreachable!("TypeId calls write_u64");
}
#[inline]
fn write_u64(&mut self, id: u64) {
self.0 = id;
}
#[inline]
fn finish(&self) -> u64 {
self.0
}
}
pub struct State {
data: HashMap<TypeId, Box<dyn Any + Send>, BuildHasherDefault<IdHasher>>,
}
impl State {
pub(crate) fn new() -> State {
State {
data: HashMap::default(),
}
}
#[doc(hidden)]
pub fn with_new<F>(f: F)
where
F: FnOnce(&mut State),
{
f(&mut State::new())
}
pub fn from_request<B>(req: Request<B>, client_addr: SocketAddr) -> Self
where
B: HttpBody<Data = Bytes> + Send + 'static,
B::Error: std::error::Error + Send + Sync,
{
let mut state = Self::new();
put_client_addr(&mut state, client_addr);
let (
request::Parts {
method,
uri,
version,
headers,
mut extensions,
..
},
body,
) = req.into_parts();
state.put(RequestPathSegments::new(uri.path()));
state.put(method);
state.put(uri);
state.put(version);
state.put(headers);
state.put(UnsyncBoxBody::new(body.map_err(io::Error::other)));
if let Some(on_upgrade) = extensions.remove::<OnUpgrade>() {
state.put(on_upgrade);
}
{
let request_id = set_request_id(&mut state);
debug!(
"[DEBUG][{}][Thread][{:?}]",
request_id,
std::thread::current().id(),
);
};
state
}
pub fn put<T>(&mut self, t: T)
where
T: StateData,
{
let type_id = TypeId::of::<T>();
trace!(" inserting record to state for type_id `{:?}`", type_id);
self.data.insert(type_id, Box::new(t));
}
pub fn has<T>(&self) -> bool
where
T: StateData,
{
let type_id = TypeId::of::<T>();
self.data.contains_key(&type_id)
}
pub fn try_borrow<T>(&self) -> Option<&T>
where
T: StateData,
{
let type_id = TypeId::of::<T>();
trace!(" borrowing state data for type_id `{:?}`", type_id);
self.data.get(&type_id).and_then(|b| b.downcast_ref::<T>())
}
pub fn borrow<T>(&self) -> &T
where
T: StateData,
{
self.try_borrow()
.expect("required type is not present in State container")
}
pub fn try_borrow_mut<T>(&mut self) -> Option<&mut T>
where
T: StateData,
{
let type_id = TypeId::of::<T>();
trace!(" mutably borrowing state data for type_id `{:?}`", type_id);
self.data
.get_mut(&type_id)
.and_then(|b| b.downcast_mut::<T>())
}
pub fn borrow_mut<T>(&mut self) -> &mut T
where
T: StateData,
{
self.try_borrow_mut()
.expect("required type is not present in State container")
}
pub fn try_take<T>(&mut self) -> Option<T>
where
T: StateData,
{
let type_id = TypeId::of::<T>();
trace!(
" taking ownership from state data for type_id `{:?}`",
type_id
);
self.data
.remove(&type_id)
.and_then(|b| b.downcast::<T>().ok())
.map(|b| *b)
}
pub fn take<T>(&mut self) -> T
where
T: StateData,
{
self.try_take()
.expect("required type is not present in State container")
}
}