pub(crate) mod client_addr;
mod data;
mod from_state;
pub mod request_id;
use log::{debug, trace};
use http::request;
use hyper::upgrade::OnUpgrade;
use hyper::{Body, Request};
use std::any::{Any, TypeId};
use std::collections::HashMap;
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;
pub struct State {
data: HashMap<TypeId, Box<dyn Any + Send>>,
}
impl State {
pub(crate) fn new() -> State {
State {
data: HashMap::new(),
}
}
#[doc(hidden)]
pub fn with_new<F>(f: F)
where
F: FnOnce(&mut State),
{
f(&mut State::new())
}
pub fn from_request(req: Request<Body>, client_addr: SocketAddr) -> Self {
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(body);
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.get(&type_id).is_some()
}
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")
}
}