use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;
use crate::http::{Request, Response};
use crate::{Depot, Handler};
#[derive(Default)]
pub struct FlowCtrl {
catching: Option<bool>,
is_ceased: bool,
pub(crate) cursor: usize,
pub(crate) handlers: Vec<Arc<dyn Handler>>,
}
impl Debug for FlowCtrl {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("FlowCtrl")
.field("catching", &self.catching)
.field("is_ceased", &self.is_ceased)
.field("cursor", &self.cursor)
.finish()
}
}
impl FlowCtrl {
#[inline]
#[must_use]
pub fn new(handlers: Vec<Arc<dyn Handler>>) -> Self {
Self {
catching: None,
is_ceased: false,
cursor: 0,
handlers,
}
}
#[inline]
#[must_use]
pub fn has_next(&self) -> bool {
self.cursor < self.handlers.len() }
#[inline]
pub async fn call_next(
&mut self,
req: &mut Request,
depot: &mut Depot,
res: &mut Response,
) -> bool {
if self.catching.is_none() {
self.catching = Some(res.is_stamped());
}
if !self.catching.unwrap_or_default() && res.is_stamped() {
self.skip_rest();
return false;
}
let mut handler = self.handlers.get(self.cursor).cloned();
if handler.is_none() {
false
} else {
while let Some(h) = handler.take() {
self.cursor += 1;
h.handle(req, depot, res, self).await;
if !self.catching.unwrap_or_default() && res.is_stamped() {
self.skip_rest();
return true;
} else if self.has_next() {
handler = self.handlers.get(self.cursor).cloned();
}
}
true
}
}
#[inline]
pub fn skip_rest(&mut self) {
self.cursor = self.handlers.len()
}
#[inline]
#[must_use]
pub fn is_ceased(&self) -> bool {
self.is_ceased
}
#[inline]
pub fn cease(&mut self) {
self.skip_rest();
self.is_ceased = true;
}
}