use std::{cell::RefCell, marker::PhantomData, rc::Rc};
use crate::event::{After, BodyEvent, EventData, HeadersAccessor, HeadersEvent};
use super::{
body::BodyExchange,
dynamic_exchange::{DynamicExchange, ExchangeEvent},
entity::HeadersHandler,
};
pub struct HeadersExchange<H, B> {
pub(super) contains_body: bool,
exchange: Rc<RefCell<DynamicExchange>>,
_events: PhantomData<(H, B)>,
}
impl<H, B> HeadersExchange<H, B>
where
H: HeadersEvent + ExchangeEvent,
B: BodyEvent + After<H> + ExchangeEvent,
{
pub(super) fn new(exchange: Rc<RefCell<DynamicExchange>>, contains_body: bool) -> Self {
Self {
contains_body,
exchange,
_events: PhantomData,
}
}
}
impl<H, B> HeadersExchange<H, B>
where
H: HeadersEvent + ExchangeEvent,
{
pub fn with_event_data<F, T>(&self, op: F) -> T
where
for<'e> F: FnOnce(&EventData<'e, H>) -> T,
{
let exchange = self.exchange.borrow();
let exchange = exchange
.get::<H>()
.expect("Exchange should be in Headers event");
let event = exchange
.event_data()
.expect("Exchange should be in Headers event");
op(&event)
}
}
impl<H, B> HeadersExchange<H, B>
where
H: HeadersEvent + ExchangeEvent,
B: BodyEvent + After<H> + ExchangeEvent + 'static,
for<'e> EventData<'e, H>: HeadersAccessor,
{
pub async fn into_body_state(self) -> BodyExchange<B> {
BodyExchange::new(self.exchange, self.contains_body).await
}
pub fn handler(&self) -> &dyn HeadersHandler {
self
}
}
impl<H, B> HeadersHandler for HeadersExchange<H, B>
where
H: HeadersEvent + ExchangeEvent,
for<'e> EventData<'e, H>: HeadersAccessor,
{
fn headers(&self) -> Vec<(String, String)> {
self.with_event_data(|e| e.headers())
}
fn header(&self, name: &str) -> Option<String> {
self.with_event_data(|e| e.header(name))
}
fn add_header(&self, name: &str, value: &str) {
self.with_event_data(|e| e.add_header(name, value))
}
fn set_header(&self, name: &str, value: &str) {
self.with_event_data(|e| e.set_header(name, value))
}
fn set_headers(&self, headers: Vec<(&str, &str)>) {
self.with_event_data(|e| e.set_headers(headers))
}
fn remove_header(&self, name: &str) {
self.with_event_data(|e| e.remove_header(name))
}
}