use crate::{
Body, HeaderName, HeaderValues, Headers, Method, Status, Swansong, Transport, TypeSet, Version,
request_body::RequestBody, type_set::Entry,
};
use std::{
any::Any,
fmt::{self, Debug, Formatter},
future::Future,
net::IpAddr,
time::Instant,
};
pub struct Conn {
pub(crate) inner: trillium_http::Conn<Box<dyn Transport>>,
halted: bool,
path: Vec<String>,
}
impl Debug for Conn {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Conn")
.field("inner", &self.inner)
.field("halted", &self.halted)
.field("path", &self.path)
.finish()
}
}
impl<T: Transport + 'static> From<trillium_http::Conn<T>> for Conn {
fn from(inner: trillium_http::Conn<T>) -> Self {
Self {
inner: inner.map_transport(|t| Box::new(t) as Box<dyn Transport>),
halted: false,
path: vec![],
}
}
}
impl Conn {
#[must_use]
pub fn ok(self, body: impl Into<Body>) -> Self {
self.with_status(200).with_body(body).halt()
}
pub fn status(&self) -> Option<Status> {
self.inner.status()
}
pub fn set_status(&mut self, status: impl TryInto<Status>) -> &mut Self {
self.inner.set_status(status);
self
}
#[must_use]
pub fn with_status(mut self, status: impl TryInto<Status>) -> Self {
self.set_status(status);
self
}
#[must_use]
pub fn with_body(mut self, body: impl Into<Body>) -> Self {
self.set_body(body);
self
}
pub fn set_body(&mut self, body: impl Into<Body>) -> &mut Self {
self.inner.set_response_body(body);
self
}
pub fn take_response_body(&mut self) -> Option<Body> {
self.inner.take_response_body()
}
pub fn response_body(&self) -> Option<&Body> {
self.inner.response_body()
}
pub fn state<T: Send + Sync + 'static>(&self) -> Option<&T> {
self.inner.state().get()
}
pub fn state_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
self.inner.state_mut().get_mut()
}
pub fn insert_state<T: Send + Sync + 'static>(&mut self, state: T) -> Option<T> {
self.inner.state_mut().insert(state)
}
#[must_use]
pub fn with_state<T: Send + Sync + 'static>(mut self, state: T) -> Self {
self.insert_state(state);
self
}
pub fn take_state<T: Send + Sync + 'static>(&mut self) -> Option<T> {
self.inner.state_mut().take()
}
pub fn state_entry<T: Send + Sync + 'static>(&mut self) -> Entry<'_, T> {
self.inner.state_mut().entry()
}
pub fn shared_state<T: Send + Sync + 'static>(&self) -> Option<&T> {
self.inner.shared_state().get()
}
pub fn request_body(&mut self) -> RequestBody<'_> {
self.inner.request_body().into()
}
#[allow(clippy::missing_errors_doc)] pub async fn request_body_string(&mut self) -> trillium_http::Result<String> {
self.request_body().read_string().await
}
pub fn response_len(&self) -> Option<u64> {
self.inner.response_body().and_then(Body::len)
}
pub fn method(&self) -> Method {
self.inner.method()
}
pub fn response_headers(&self) -> &Headers {
self.inner.response_headers()
}
pub fn response_headers_mut(&mut self) -> &mut Headers {
self.inner.response_headers_mut()
}
pub fn request_headers(&self) -> &Headers {
self.inner.request_headers()
}
pub fn request_headers_mut(&mut self) -> &mut Headers {
self.inner.request_headers_mut()
}
pub fn request_trailers(&self) -> Option<&Headers> {
self.inner.request_trailers()
}
#[must_use]
pub fn with_response_header(
mut self,
header_name: impl Into<HeaderName<'static>>,
header_value: impl Into<HeaderValues>,
) -> Self {
self.insert_response_header(header_name, header_value);
self
}
pub fn insert_response_header(
&mut self,
header_name: impl Into<HeaderName<'static>>,
header_value: impl Into<HeaderValues>,
) {
self.response_headers_mut()
.insert(header_name, header_value);
}
pub fn path(&self) -> &str {
self.path.last().map_or_else(|| self.inner.path(), |p| &**p)
}
pub fn querystring(&self) -> &str {
self.inner.querystring()
}
#[must_use]
pub const fn halt(mut self) -> Self {
self.set_halted(true);
self
}
pub const fn set_halted(&mut self, halted: bool) -> &mut Self {
self.halted = halted;
self
}
pub const fn is_halted(&self) -> bool {
self.halted
}
pub fn is_secure(&self) -> bool {
self.inner.is_secure()
}
pub fn start_time(&self) -> Instant {
self.inner.start_time()
}
pub fn into_inner<T: Transport>(self) -> trillium_http::Conn<T> {
self.inner.map_transport(|t| {
*(t as Box<dyn Any>)
.downcast()
.expect("attempted to downcast to the wrong transport type")
})
}
pub fn peer_ip(&self) -> Option<IpAddr> {
self.inner.peer_ip()
}
pub fn set_peer_ip(&mut self, peer_ip: Option<IpAddr>) -> &mut Self {
self.inner.set_peer_ip(peer_ip);
self
}
pub fn push_path(&mut self, path: String) {
self.path.push(path);
}
pub fn pop_path(&mut self) {
self.path.pop();
}
pub async fn cancel_on_disconnect<'a, Fut>(&'a mut self, fut: Fut) -> Option<Fut::Output>
where
Fut: Future + Send + 'a,
{
self.inner.cancel_on_disconnect(fut).await
}
pub async fn is_disconnected(&mut self) -> bool {
self.inner.is_disconnected().await
}
pub fn http_version(&self) -> Version {
self.inner.http_version()
}
pub fn host(&self) -> Option<&str> {
self.inner.host()
}
pub fn path_and_query(&self) -> &str {
self.inner.path_and_query()
}
pub fn swansong(&self) -> Swansong {
self.inner.swansong()
}
}
impl AsMut<trillium_http::Conn<Box<dyn Transport>>> for Conn {
fn as_mut(&mut self) -> &mut trillium_http::Conn<Box<dyn Transport>> {
&mut self.inner
}
}
impl AsRef<trillium_http::Conn<Box<dyn Transport>>> for Conn {
fn as_ref(&self) -> &trillium_http::Conn<Box<dyn Transport>> {
&self.inner
}
}
impl AsMut<TypeSet> for Conn {
fn as_mut(&mut self) -> &mut TypeSet {
self.inner.state_mut()
}
}
impl AsRef<TypeSet> for Conn {
fn as_ref(&self) -> &TypeSet {
self.inner.state()
}
}