use crate::frame::{FrameHeader, FrameHeaderParser};
use crate::headers::HeaderBlockId;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct StreamId(
pub u64,
);
impl StreamId {
pub fn is_uni(self) -> bool {
self.0 & 0x2 != 0
}
pub fn is_client_initiated(self) -> bool {
self.0 & 0x1 == 0
}
pub fn is_request(self) -> bool {
self.0 % 4 == 0
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum UniKind {
Control,
QpackEncoder,
QpackDecoder,
}
#[derive(Default)]
pub(crate) struct Stream {
pub send: SendState,
pub recv: RecvState,
pub terminal_emitted: bool,
}
#[derive(Default)]
pub(crate) struct RecvState {
pub parser: FrameHeaderParser,
pub cur: Option<(FrameHeader, u64)>,
pub phase: RecvPhase,
pub headers_buf: Vec<u8>,
pub unreleased: Option<HeaderBlockId>,
pub content_length: Option<u64>,
pub data_received: u64,
pub tunnel: TunnelState,
pub expects_no_content: bool,
pub delivered: bool,
pub closed: bool,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum RecvPhase {
#[default]
AwaitHeaders,
AfterInformational,
Body,
AfterTrailers,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum TunnelState {
#[default]
Regular,
ConnectPending,
Tunnel,
}
#[derive(Default)]
pub(crate) struct SendState {
pub queue: Vec<u8>,
pub read: usize,
pub phase: SendPhase,
pub in_flight: Option<InFlight>,
pub request_is_head: bool,
pub no_content_status: bool,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) enum SendPhase {
#[default]
Idle,
Headers,
Body,
Tunnel,
Trailers,
Ending,
Done,
}
pub(crate) struct InFlight {
pub frame_len: u64,
pub written: u64,
}
impl Stream {
pub fn connect_final(&mut self, success: bool) {
if self.recv.tunnel != TunnelState::ConnectPending {
return;
}
if success {
self.enter_tunnel();
} else {
self.recv.tunnel = TunnelState::Regular;
}
}
fn enter_tunnel(&mut self) {
self.recv.tunnel = TunnelState::Tunnel;
if self.send.phase == SendPhase::Body {
self.send.phase = SendPhase::Tunnel;
}
}
}
impl SendState {
pub fn pending(&self) -> &[u8] {
if self.in_flight.is_some() {
return &[];
}
self.queue.get(self.read..).unwrap_or_default()
}
pub fn drained(&self) -> bool {
self.in_flight.is_none() && self.queue.is_empty()
}
pub fn stop(&mut self) {
*self = SendState {
phase: SendPhase::Done,
..SendState::default()
};
}
pub fn advance(&mut self, n: usize) {
self.read += n;
if self.read == self.queue.len() {
self.queue = Vec::new();
self.read = 0;
}
}
}