#![allow(missing_docs)]
#[derive(Debug, Clone)]
pub struct StreamCapacity {
connection_send: i32,
stream_send: i32,
receive_window: i32,
initial_window: i32,
is_blocked: bool,
}
impl StreamCapacity {
pub const DEFAULT_WINDOW: i32 = 65535;
pub fn new() -> Self {
Self {
connection_send: Self::DEFAULT_WINDOW,
stream_send: Self::DEFAULT_WINDOW,
receive_window: Self::DEFAULT_WINDOW,
initial_window: Self::DEFAULT_WINDOW,
is_blocked: false,
}
}
pub fn with_initial_window(initial: i32) -> Self {
Self {
connection_send: initial,
stream_send: initial,
receive_window: initial,
initial_window: initial,
is_blocked: false,
}
}
pub fn reserve_send(&mut self, bytes: i32) -> Result<(), FlowControlError> {
if bytes < 0 {
return Err(FlowControlError::NegativeReservation);
}
let available = self.available_send();
if bytes > available {
self.is_blocked = true;
return Err(FlowControlError::InsufficientCapacity { requested: bytes, available });
}
self.stream_send -= bytes;
self.connection_send -= bytes;
self.is_blocked = false;
Ok(())
}
pub fn release_send(&mut self, bytes: i32) {
self.stream_send += bytes;
self.connection_send += bytes;
if self.available_send() > 0 {
self.is_blocked = false;
}
}
pub fn consume_receive(&mut self, bytes: i32) {
self.receive_window -= bytes;
}
pub fn replenish_receive(&mut self, bytes: i32) {
self.receive_window += bytes;
}
#[must_use]
pub fn available_send(&self) -> i32 {
self.stream_send.min(self.connection_send).max(0)
}
#[must_use]
pub fn available_receive(&self) -> i32 {
self.receive_window.max(0)
}
#[must_use]
pub fn is_blocked(&self) -> bool {
self.is_blocked
}
#[must_use]
pub fn needs_window_update(&self) -> bool {
self.receive_window < self.initial_window / 2
}
}
impl Default for StreamCapacity {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FlowControlError {
NegativeReservation,
InsufficientCapacity { requested: i32, available: i32 },
}