use std::fmt;
use std::fmt::Write;
pub type Result<T> = std::result::Result<T, Http3Error>;
#[derive(Default)]
pub struct Http3Config {
max_field_section_size: Option<u64>,
qpack_max_table_capacity: Option<u64>,
qpack_blocked_streams: Option<u64>,
}
impl Http3Config {
pub const fn new() -> Result<Http3Config> {
Ok(Http3Config {
max_field_section_size: None,
qpack_max_table_capacity: None,
qpack_blocked_streams: None,
})
}
pub fn set_max_field_section_size(&mut self, v: u64) {
self.max_field_section_size = Some(v);
}
pub fn set_qpack_max_table_capacity(&mut self, v: u64) {
self.qpack_max_table_capacity = Some(v);
}
pub fn set_qpack_blocked_streams(&mut self, v: u64) {
self.qpack_blocked_streams = Some(v);
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Http3Event {
Headers {
headers: Vec<Header>,
fin: bool,
},
Data,
Finished,
Reset(u64),
GoAway,
PriorityUpdate,
}
pub struct Http3Headers<'a> {
pub(crate) headers: &'a Vec<Header>,
}
pub trait NameValue {
fn name(&self) -> &[u8];
fn value(&self) -> &[u8];
}
impl NameValue for (&[u8], &[u8]) {
fn name(&self) -> &[u8] {
self.0
}
fn value(&self) -> &[u8] {
self.1
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct Header(Vec<u8>, Vec<u8>);
impl Header {
pub fn new(name: &[u8], value: &[u8]) -> Self {
Self(name.to_vec(), value.to_vec())
}
}
impl NameValue for Header {
fn name(&self) -> &[u8] {
&self.0
}
fn value(&self) -> &[u8] {
&self.1
}
}
impl fmt::Debug for Header {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('"')?;
fmt_readable(&self.0, f)?;
f.write_str(": ")?;
fmt_readable(&self.1, f)?;
f.write_char('"')
}
}
fn fmt_readable(hdr: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
match std::str::from_utf8(hdr) {
Ok(s) => f.write_str(&s.escape_default().to_string()),
Err(_) => write!(f, "{hdr:?}"),
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct HeaderRef<'a>(&'a [u8], &'a [u8]);
impl<'a> HeaderRef<'a> {
pub const fn new(name: &'a [u8], value: &'a [u8]) -> Self {
Self(name, value)
}
}
impl NameValue for HeaderRef<'_> {
fn name(&self) -> &[u8] {
self.0
}
fn value(&self) -> &[u8] {
self.1
}
}
pub trait Http3Handler {
fn on_stream_headers(&self, stream_id: u64, event: &mut Http3Event);
fn on_stream_data(&self, stream_id: u64);
fn on_stream_finished(&self, stream_id: u64);
fn on_stream_reset(&self, stream_id: u64, error_code: u64);
fn on_stream_priority_update(&self, stream_id: u64);
fn on_conn_goaway(&self, stream_id: u64);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fmt_readable() {
let h = Header::new(b"proto", b"h3");
assert_eq!(format!("{:?}", h), "\"proto: h3\"");
let h = Header::new(b"proto", &vec![0x97, 0x61, 0x6c]);
assert_eq!(format!("{:?}", h), "\"proto: [151, 97, 108]\"");
}
#[test]
fn header_ref() {
let name = b"x-powered-by";
let value = b"tquic";
let h = HeaderRef::new(name, value);
assert_eq!(h.name(), name);
assert_eq!(h.value(), value);
}
}
pub use error::Http3Error;
#[path = "qpack/qpack.rs"]
mod qpack;
pub mod connection;
mod error;
mod frame;
mod stream;