use crate::settings::{
DEFAULT_HEADER_TABLE_SIZE, DEFAULT_INITIAL_WINDOW_SIZE, DEFAULT_MAX_FRAME_SIZE,
MAX_INITIAL_WINDOW_SIZE, MAX_MAX_FRAME_SIZE, MIN_MAX_FRAME_SIZE, WtInitialSettings,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Limits {
pub max_concurrent_streams: Option<u32>,
pub initial_window_size: u32,
pub max_frame_size: u32,
pub max_header_list_size: Option<u32>,
pub header_table_size: u32,
pub connection_window_size: u32,
pub enable_connect_protocol: bool,
pub no_rfc7540_priorities: bool,
pub wt_initial: WtInitialSettings,
}
impl Default for Limits {
fn default() -> Self {
Self {
max_concurrent_streams: Some(100),
initial_window_size: DEFAULT_INITIAL_WINDOW_SIZE,
max_frame_size: DEFAULT_MAX_FRAME_SIZE,
max_header_list_size: Some(16384),
header_table_size: DEFAULT_HEADER_TABLE_SIZE,
connection_window_size: DEFAULT_INITIAL_WINDOW_SIZE,
enable_connect_protocol: false,
no_rfc7540_priorities: false,
wt_initial: WtInitialSettings::default(),
}
}
}
impl Limits {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub const fn with_max_concurrent_streams(mut self, max: Option<u32>) -> Self {
self.max_concurrent_streams = max;
self
}
#[must_use]
pub fn with_initial_window_size(mut self, size: u32) -> Self {
assert!(
size <= MAX_INITIAL_WINDOW_SIZE,
"initial window size must be <= {MAX_INITIAL_WINDOW_SIZE}"
);
self.initial_window_size = size;
self
}
#[must_use]
pub fn with_max_frame_size(mut self, size: u32) -> Self {
assert!(
(MIN_MAX_FRAME_SIZE..=MAX_MAX_FRAME_SIZE).contains(&size),
"max frame size must be {MIN_MAX_FRAME_SIZE}..={MAX_MAX_FRAME_SIZE}"
);
self.max_frame_size = size;
self
}
#[must_use]
pub const fn with_max_header_list_size(mut self, size: Option<u32>) -> Self {
self.max_header_list_size = size;
self
}
#[must_use]
pub const fn with_header_table_size(mut self, size: u32) -> Self {
self.header_table_size = size;
self
}
#[must_use]
pub fn with_connection_window_size(mut self, size: u32) -> Self {
assert!(
size <= MAX_INITIAL_WINDOW_SIZE,
"connection window size must be <= {MAX_INITIAL_WINDOW_SIZE}"
);
self.connection_window_size = size;
self
}
#[must_use]
pub const fn with_enable_connect_protocol(mut self, enable: bool) -> Self {
self.enable_connect_protocol = enable;
self
}
#[must_use]
pub const fn with_no_rfc7540_priorities(mut self, enable: bool) -> Self {
self.no_rfc7540_priorities = enable;
self
}
#[must_use]
pub fn with_webtransport(mut self, wt_initial: WtInitialSettings) -> Self {
self.wt_initial = wt_initial;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_limits() {
let limits = Limits::default();
assert_eq!(limits.max_concurrent_streams, Some(100));
assert_eq!(limits.initial_window_size, 65535);
assert_eq!(limits.max_frame_size, 16384);
}
#[test]
fn test_builder_pattern() {
let limits = Limits::new()
.with_max_concurrent_streams(Some(50))
.with_initial_window_size(1 << 20)
.with_max_frame_size(1 << 20);
assert_eq!(limits.max_concurrent_streams, Some(50));
assert_eq!(limits.initial_window_size, 1 << 20);
assert_eq!(limits.max_frame_size, 1 << 20);
}
#[test]
#[should_panic]
fn test_invalid_initial_window_size() {
let _ = Limits::new().with_initial_window_size(MAX_INITIAL_WINDOW_SIZE + 1);
}
#[test]
#[should_panic]
fn test_invalid_max_frame_size_too_small() {
let _ = Limits::new().with_max_frame_size(MIN_MAX_FRAME_SIZE - 1);
}
#[test]
#[should_panic]
fn test_invalid_max_frame_size_too_large() {
let _ = Limits::new().with_max_frame_size(MAX_MAX_FRAME_SIZE + 1);
}
}