use std::cell::RefCell;
use std::future::{ready, Ready};
use std::rc::Rc;
use crate::event::{EventKind, RequestBody, RequestHeaders};
use crate::BoxFuture;
use super::body::BodyExchange;
use super::dynamic_exchange::DynamicExchange;
use super::entity::IntoBodyState;
use super::headers::HeadersExchange;
use super::{BodyState, EntityState, HeadersState};
pub struct RequestState {
contains_body: bool,
exchange: Rc<RefCell<DynamicExchange>>,
}
#[derive(thiserror::Error, Debug)]
pub enum InvalidRequestState {
#[error("Invalid request state: {0:?}")]
Event(EventKind),
#[error("Early response")]
EarlyResponse,
}
impl RequestState {
#[allow(clippy::await_holding_refcell_ref)]
pub(crate) async fn new(
exchange: Rc<RefCell<DynamicExchange>>,
) -> Result<Self, InvalidRequestState> {
let contains_body;
{
let mut exchange_ref = exchange.borrow_mut();
let Some(exchange) = exchange_ref.wait_for_event::<RequestHeaders>().await else {
let error = exchange
.borrow()
.current_event()
.map(InvalidRequestState::Event)
.unwrap_or(InvalidRequestState::EarlyResponse);
return Err(error);
};
contains_body = !exchange
.event_data()
.expect("Must contain headers")
.event
.end_of_stream;
}
Ok(Self {
contains_body,
exchange,
})
}
}
impl IntoBodyState for RequestState {
type BodyState = RequestBodyState;
type BodyStateFuture = BoxFuture<'static, Self::BodyState>;
fn into_body_state(self) -> Self::BodyStateFuture {
Box::pin(async {
RequestBodyState {
inner: BodyExchange::new(self.exchange, self.contains_body).await,
}
})
}
}
impl EntityState for RequestState {
type HeadersState = RequestHeadersState;
type HeadersStateFuture = Ready<Self::HeadersState>;
fn into_headers_state(self) -> Self::HeadersStateFuture {
ready(RequestHeadersState {
inner: HeadersExchange::new(self.exchange, self.contains_body),
})
}
}
pub struct RequestHeadersState {
inner: HeadersExchange<RequestHeaders, RequestBody>,
}
impl RequestHeadersState {
pub fn method(&self) -> String {
self.inner.with_event_data(|e| e.method())
}
pub fn scheme(&self) -> String {
self.inner.with_event_data(|e| e.scheme())
}
pub fn authority(&self) -> String {
self.inner.with_event_data(|e| e.authority())
}
pub fn path(&self) -> String {
self.inner.with_event_data(|e| e.path())
}
}
impl IntoBodyState for RequestHeadersState {
type BodyState = RequestBodyState;
type BodyStateFuture = BoxFuture<'static, Self::BodyState>;
fn into_body_state(self) -> Self::BodyStateFuture {
Box::pin(async {
RequestBodyState {
inner: self.inner.into_body_state().await,
}
})
}
}
impl HeadersState for RequestHeadersState {
fn handler(&self) -> &dyn super::HeadersHandler {
self.inner.handler()
}
fn contains_body(&self) -> bool {
self.inner.contains_body
}
}
pub struct RequestBodyState {
inner: BodyExchange<RequestBody>,
}
impl BodyState for RequestBodyState {
fn handler(&self) -> &dyn super::BodyHandler {
&self.inner
}
fn contains_body(&self) -> bool {
self.inner.contains_body()
}
}