use std::time::Instant;
use bytes::{Bytes, BytesMut};
use http::{HeaderMap, Method, StatusCode, Uri, Version};
use crate::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ExchangeId(pub u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Capacity {
Unique { available: bool },
Shared { open: usize, max: usize },
}
#[derive(Debug, Clone)]
pub struct RequestHead {
pub method: Method,
pub uri: Uri,
pub version: Version,
pub headers: HeaderMap,
}
#[derive(Debug, Clone)]
pub struct ResponseHead {
pub status: StatusCode,
pub version: Version,
pub headers: HeaderMap,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum OpenError {
Full,
GoingAway,
Closed,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum NetAction {
Send(Bytes),
Flush,
Close,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum Event {
Informational(ResponseHead),
Head(ResponseHead),
Data(Bytes),
Trailers(HeaderMap),
End,
Reset(Error),
Writable,
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum ConnEvent {
GoingAway,
Closed(Option<Error>),
}
#[derive(Debug, Default)]
pub struct Output {
pub net: Vec<NetAction>,
pub events: Vec<(ExchangeId, Event)>,
pub conn: Vec<ConnEvent>,
}
impl Output {
pub fn is_empty(&self) -> bool {
self.net.is_empty() && self.events.is_empty() && self.conn.is_empty()
}
}
pub trait Engine {
fn capacity(&self) -> Capacity;
fn open(&mut self, head: RequestHead, now: Instant, out: &mut Output) -> Result<ExchangeId, OpenError>;
fn send_body(&mut self, id: ExchangeId, data: Bytes, end: bool, out: &mut Output) -> usize;
fn consumed(&mut self, id: ExchangeId, n: usize, out: &mut Output);
fn reset(&mut self, id: ExchangeId, out: &mut Output);
fn on_bytes(&mut self, input: &mut BytesMut, out: &mut Output);
fn on_eof(&mut self, out: &mut Output);
fn on_tick(&mut self, now: Instant, out: &mut Output);
fn next_deadline(&self) -> Option<Instant>;
fn close(&mut self, out: &mut Output);
}