Skip to main content

simoom_qpack/
lib.rs

1//! QPACK (RFC 9204) for simoom.
2//!
3//! - [`Decoder`]: bounded dynamic table, blocked streams with a limit, encoder-stream input and
4//!   decoder-stream output.
5//! - [`Encoder`]: static table only by default; [`Encoder::with_dynamic_table`] enables a
6//!   dynamic table that never evicts unacknowledged or referenced entries and respects the
7//!   peer's blocked-streams limit.
8//! - [`huffman`]: the RFC 7541 Huffman code.
9#![forbid(unsafe_code)]
10
11mod decoder;
12mod encoder;
13pub mod huffman;
14mod prim;
15
16pub use decoder::{Decoded, Decoder};
17pub use encoder::Encoder;
18pub use prim::{put_int, MAX_INT, STATIC_TABLE};
19
20/// One field line: a name and a value.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct Field {
23    pub name: Vec<u8>,
24    pub value: Vec<u8>,
25}
26
27impl Field {
28    pub fn new(name: impl Into<Vec<u8>>, value: impl Into<Vec<u8>>) -> Self {
29        Field { name: name.into(), value: value.into() }
30    }
31
32    /// Size of the field for limits and the dynamic table: name + value + 32.
33    pub fn size(&self) -> u64 {
34        self.name.len() as u64 + self.value.len() as u64 + 32
35    }
36}
37
38/// QPACK errors. [`Error::code`] gives the HTTP/3 error code.
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum Error {
41    /// QPACK_DECOMPRESSION_FAILED (0x200).
42    DecompressionFailed,
43    /// QPACK_ENCODER_STREAM_ERROR (0x201).
44    EncoderStream,
45    /// QPACK_DECODER_STREAM_ERROR (0x202).
46    DecoderStream,
47    /// The decoded field section exceeds the configured maximum (RFC 9114 4.2.2). HTTP/3
48    /// treats it as a malformed request or response, not a QPACK failure.
49    FieldSectionTooLarge,
50    /// The section needs dynamic-table entries that have not arrived yet (internal).
51    Blocked,
52}
53
54impl Error {
55    /// HTTP/3 error code for this error.
56    pub fn code(&self) -> u64 {
57        match self {
58            Error::EncoderStream => 0x201,
59            Error::DecoderStream => 0x202,
60            _ => 0x200,
61        }
62    }
63}
64
65impl std::fmt::Display for Error {
66    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67        let s = match self {
68            Error::DecompressionFailed => "QPACK decompression failed",
69            Error::EncoderStream => "QPACK encoder stream error",
70            Error::DecoderStream => "QPACK decoder stream error",
71            Error::FieldSectionTooLarge => "field section too large",
72            Error::Blocked => "QPACK field section blocked",
73        };
74        f.write_str(s)
75    }
76}
77
78impl std::error::Error for Error {}