# flare.http3.server

> A module of flare_mlake's API.

``flare.http3.server`` -- HTTP/3 server connection driver.

Wraps the sans-I/O HTTP/3 codec primitives
(:class:`flare.http3.Http3RequestReader`,
:func:`flare.http3.encode_response_headers`) and the QUIC connection
driver (:class:`flare.quic.server.QuicConnection`) into a per-
connection HTTP/3 server.

## Stream layout (RFC 9114 §6)

HTTP/3 over QUIC uses four families of streams:

* **Bidirectional request streams** -- one per request/response
  exchange. The client opens, sends HEADERS + DATA frames; the
  server replies on the same stream with HEADERS + DATA + (FIN).
* **Unidirectional control stream** (type 0x00) -- exactly one
  per direction; carries SETTINGS first, then GOAWAY /
  MAX_PUSH_ID over the connection lifetime. The server opens its
  own as stream 3 with its first 1-RTT flight
  (:meth:`Http3Connection.take_control_stream_start`).
* **Unidirectional push stream** (type 0x01) -- server-initiated.
  Not implemented (RFC 9114 deprecates push as of revision 9).
* **Unidirectional QPACK encoder stream** (type 0x02) +
  **decoder stream** (type 0x03) -- carry dynamic-table
  instructions. The driver mirrors the peer encoder's inserts
  into a per-connection dynamic table (RFC 9204) so request
  field sections referencing dynamic entries decode, and emits
  Insert Count Increment back on the decoder stream. Dynamic-
  table use is gated on the ``qpack_max_table_capacity`` the
  SETTINGS advertise: the default (0) keeps static-only behavior.

## What ships here

- :class:`Http3Config` -- per-connection HTTP/3 config:
  max field section size, max blocked streams, the GOAWAY
  threshold above which the server stops accepting new
  request streams.
- :class:`Http3Connection` -- the per-connection driver carrier.
  Owns the per-stream :class:`Http3RequestReader` instances (keyed
  by QUIC stream ID), the per-stream accumulated request state,
  and the per-stream pending outbound bytes.
- :class:`Http3StreamType` -- the unidirectional-stream type
  codepoints from RFC 9114 §6.2.

Connection errors: an undecodable request field section sets
:attr:`Http3Connection.connection_error_code` to
``QPACK_DECOMPRESSION_FAILED`` (0x200), and the driver raises the other
H3 / QPACK connection errors with the code's name in the message
(:func:`h3_error_code` maps it back). The QUIC reactor closes the
connection with that code.

The driver is sans-I/O: the QUIC reactor feeds reassembled stream
chunks in via :meth:`Http3Connection.feed_stream_chunk` and drains
pending outbound frames via :meth:`Http3Connection.take_response_frames`.
The Handler dispatch sits on the QUIC reactor side; the H3
layer surfaces the Request once it's fully reassembled and
the reactor calls :meth:`Http3Connection.emit_response` once the
Handler returns.

References:
- RFC 9114 "HTTP/3".
- RFC 9204 "QPACK: Field Compression for HTTP/3".

## Structs

### `Http3StreamType`

```mojo
struct Http3StreamType
```

RFC 9114 §6.2 unidirectional stream types.

Each uni stream's first varint is the stream type; the reader
dispatches on this varint to the matching internal state
machine (control / push / qpack-enc / qpack-dec).

Implements: `Movable`

#### `CONTROL`

```mojo
comptime CONTROL = Int(0)
```

RFC 9114 §6.2.1 -- control stream. Carries SETTINGS, GOAWAY, MAX_PUSH_ID. Exactly one per direction.

#### `PUSH`

```mojo
comptime PUSH = Int(1)
```

RFC 9114 §6.2.2 -- push stream. Server-initiated. Deprecated as of RFC 9114 revision 9; this codepoint is carried so the reader can reject incoming push streams with H3_STREAM_CREATION_ERROR.

#### `QPACK_ENCODER`

```mojo
comptime QPACK_ENCODER = Int(2)
```

RFC 9204 §4.2 -- QPACK encoder stream. Carries dynamic- table insert instructions.

#### `QPACK_DECODER`

```mojo
comptime QPACK_DECODER = Int(3)
```

RFC 9204 §4.2 -- QPACK decoder stream. Carries section-acknowledgement + stream-cancellation instructions.

### `Http3Config`

```mojo
struct Http3Config
```

Per-connection HTTP/3 settings.

The server advertises these via the control stream's SETTINGS
frame (RFC 9114 §7.2.4). Production defaults match the values
the OpenAPI gen + the cookbook examples expect.

Implements: `Copyable`, `Defaultable`, `Movable`

Fields:

- `max_field_section_size: UInt64`: RFC 9114 §7.2.4.2 -- maximum total size (in bytes) the server will accept for a single field section. Default: 65536. The reader rejects oversize header blocks with H3_EXCESSIVE_LOAD.
- `qpack_max_table_capacity: UInt64`: RFC 9204 §3.2.2 -- maximum bytes the server is willing to spend on the QPACK dynamic table. Default 0 means static- table-only mode; the SETTINGS we emit tell the peer not to send dynamic-table inserts.
- `qpack_blocked_streams: UInt64`: RFC 9204 §3.2.3 -- maximum streams the server is willing to leave blocked on QPACK dynamic-table insertions. Default 0 (paired with qpack_max_table_capacity=0).
- `enable_connect_protocol: Bool`: RFC 9220 §3 -- whether to advertise SETTINGS_ENABLE_CONNECT_PROTOCOL and accept extended CONNECT (``:protocol``) requests. Default False: advertising it obliges the server to accept such requests (RFC 8441 sec 3), and it used to be advertised while every one was refused.
- `max_body_size: UInt64`: Largest request body buffered for a handler. A request with more is answered 413 and the client asked to stop sending (RFC 9114 sec 4.1.2). Default 10 MiB, as on h2.
- `stream_request_bodies: Bool`: Hand a request with a body to the handler on its HEADERS, the body to follow through ``Request.body_stream()`` as it arrives, instead of after the whole body is buffered; credit is granted as the handler reads, so ``max_body_size`` does not apply. Default False: handlers otherwise expect the whole body in ``Request.body``.
- `h3_datagram: Bool`: RFC 9297 -- advertise SETTINGS_H3_DATAGRAM and carry HTTP Datagrams on extended CONNECT tunnels. Needs QUIC DATAGRAM support (``QuicServerConfig.max_datagram_frame_size`` > 0). Default False.
- `goaway_threshold_streams: UInt64`: Local soft cap on the stream count above which the server emits GOAWAY and refuses new request streams. Default UINT64_MAX (effectively no cap; mirrors the H2 server's behaviour).

#### `__init__`

```mojo
def __init__(out self)
```

### `Http3Connection`

```mojo
struct Http3Connection
```

Per-connection HTTP/3 server driver.

Owned by the QUIC reactor. One instance per QUIC connection
that negotiated the ``h3`` ALPN identifier. The driver:

* Tracks per-bidirectional-stream :class:`_Http3StreamState`
  instances keyed by QUIC stream ID. Each carrier owns the
  sans-I/O frame reader, the accumulated request bytes /
  headers / body / trailers, and the pending outbound
  response bytes.
* Carries the SETTINGS the server announced + the client
  announced.
* Tracks the control-stream lifecycle (whether the peer's
  SETTINGS arrived yet, whether GOAWAY was emitted).
* Carries the QPACK state, including a per-connection dynamic
  table (RFC 9204) mirroring the peer encoder's inserts when
  ``qpack_max_table_capacity`` is advertised non-zero.

The driver is sans-I/O: the QUIC reactor feeds reassembled
stream chunks in via :meth:`feed_stream_chunk` and drains
pending outbound frames via :meth:`take_response_frames`.
The Handler dispatch happens on the reactor side -- the H3
layer surfaces the assembled :class:`Request` via
:meth:`take_request` and accepts the matching
:class:`Response` via :meth:`emit_response`.

Implements: `Copyable`, `Defaultable`, `Movable`

Fields:

- `config: Http3Config`: Local configuration -- the values the server advertises via SETTINGS.
- `peer_settings_received: Bool`: Whether the peer's SETTINGS frame has arrived on the control stream yet. Until True, the driver buffers any application traffic that would depend on the negotiated field-section-size + QPACK parameters.
- `goaway_emitted: Bool`: Whether the server has emitted GOAWAY. Once True, request streams at or above :attr:`goaway_id` are rejected.
- `goaway_id: UInt64`: The stream id the GOAWAY named: requests below it are still served (RFC 9114 sec 5.2), so one reordered behind the GOAWAY is not lost.
- `streams: Dict[Int, _Http3StreamState]`: Per-stream state carriers. Keys are QUIC stream IDs. Streams are removed via :meth:`close_request_stream` once the response is fully drained from the outbox.
- `control_stream_id: Int`: QUIC stream ID of the locally-opened control stream. -1 until the driver opens the control stream during connection setup.
- `qpack_encoder_stream_id: Int`: QUIC stream ID of the locally-opened QPACK encoder stream. -1 in static-only mode.
- `qpack_decoder_stream_id: Int`: QUIC stream ID of the locally-opened QPACK decoder stream. -1 in static-only mode.
- `peer_control_stream_id: Int`: QUIC stream ID of the peer's control stream once observed. -1 until the peer's uni-stream type prefix (0x00) is read. RFC 9114 §6.2.1: at most one peer control stream per direction; a second control stream is H3_STREAM_CREATION_ERROR.
- `peer_qpack_encoder_stream_id: Int`: RFC 9204 §4.2 -- peer's QPACK encoder uni-stream. -1 until the type prefix (0x02) arrives.
- `peer_qpack_decoder_stream_id: Int`: RFC 9204 §4.2 -- peer's QPACK decoder uni-stream. -1 until the type prefix (0x03) arrives.
- `peer_settings_max_field_section_size: UInt64`: RFC 9114 §7.2.4.2 -- peer-advertised maximum field section size. UINT64_MAX until the peer's SETTINGS frame arrives.
- `peer_settings_qpack_max_table_capacity: UInt64`: RFC 9204 §3.2.2 -- peer-advertised QPACK dynamic-table capacity. 0 until the peer's SETTINGS frame arrives + only non-zero if the peer opts into dynamic-table inserts.
- `peer_settings_qpack_blocked_streams: UInt64`: RFC 9204 §3.2.3 -- peer-advertised blocked-streams budget. 0 until the peer's SETTINGS frame arrives.
- `peer_settings_enable_connect_protocol: Bool`: RFC 9220 §3 -- whether the peer advertises CONNECT- Protocol support.
- `peer_settings_h3_datagram: Bool`: RFC 9297 -- the peer sent SETTINGS_H3_DATAGRAM = 1.
- `peer_quic_datagram: Bool`: Set by the QUIC layer: the peer advertised a non-zero ``max_datagram_frame_size``. SETTINGS_H3_DATAGRAM = 1 without it is an H3_SETTINGS_ERROR (RFC 9297 sec 2.1.1).
- `peer_goaway_max_stream_id: UInt64`: RFC 9114 §5.2 -- peer-emitted GOAWAY identifier. UINT64_MAX means no GOAWAY has arrived yet; once a GOAWAY arrives this holds the maximum stream id the peer will accept. Stream ids >= this value are aborted by the H3 layer.
- `reassembly: Dict[Int, _StreamReassembly]`: Per-stream offset reassembly in front of the readers; see :meth:`feed_stream_frame`.
- `closed_request_streams: Dict[Int, Bool]`: Client request streams answered and closed above :attr:`closed_request_floor`. A retransmitted STREAM frame for a stream the server had already answered found no state, opened it afresh and ran the request a second time.
- `closed_request_floor: Int`: Every client bidi stream id below this is closed. Advanced as streams close in order, so the tombstone set stays small.
- `peer_uni_buffers: Dict[Int, List[UInt8]]`: Per-uni-stream inbound buffer. The stream-type varint may span multiple chunks (it's at most 8 bytes but the QUIC layer may split smaller); we buffer until the type is resolvable. Once resolved, the buffer carries the remainder of the stream payload.
- `peer_uni_kinds: Dict[Int, Int]`: Per-uni-stream resolved type: 0 (control), 1 (push), 2 (qpack-enc), 3 (qpack-dec), -1 (unknown grease / reserved). Empty means the type varint has not been resolved yet on that stream.
- `qpack_table: ArcPointer[QpackDynamicTable]`: RFC 9204 QPACK dynamic table mirroring the peer encoder's insert log. Shared (by ``ArcPointer``) with every per-stream reader so a request HEADERS field section can resolve dynamic references the peer streamed over its encoder stream. Capacity is 0 (static-only) unless :attr:`config` advertises a non-zero ``qpack_max_table_capacity``.
- `pending_qpack_increment: Int`: Count of peer inserts applied since the last Insert Count Increment we emitted on our QPACK decoder stream (RFC 9204 §4.4.3). Drained by :meth:`take_qpack_decoder_frames`.
- `control_stream_sent: Bool`: Whether :meth:`take_control_stream_start` has handed the reactor the server's control-stream prefix (H3-07).
- `connection_error_code: UInt64`: Non-zero once the driver has hit an error that RFC 9114 / 9204 make a *connection* error (so far an undecodable field section, ``QPACK_DECOMPRESSION_FAILED``). The QUIC layer reads it after each feed and closes the connection with this code.
- `connection_error_reason: String`: Human-readable cause of :attr:`connection_error_code`.

#### `__init__`

```mojo
def __init__(out self)
```

#### `with_config`

```mojo
def with_config(config: Http3Config) -> Self
```

Construct with a non-default config carrier.

#### `open_request_stream`

```mojo
def open_request_stream(mut self, stream_id: Int)
```

Allocate a per-stream carrier for an inbound bidirectional QUIC stream. Idempotent: re-opening the same stream ID is a no-op (the QUIC reactor occasionally fires the open event redundantly when a stream sees both HEADERS and DATA before the dispatcher polls).

#### `close_request_stream`

```mojo
def close_request_stream(mut self, stream_id: Int)
```

Drop the per-stream carrier. Called after the response FIN has been emitted (so the server doesn't keep parser state around for a stream that's done).

#### `is_closed_request_stream`

```mojo
def is_closed_request_stream(self, stream_id: Int) -> Bool
```

Whether ``stream_id`` is a client request stream the server has already answered and closed.

#### `feed_stream_frame`

```mojo
def feed_stream_frame(mut self, stream_id: Int, offset: UInt64, data: Span[UInt8], fin: Bool)
```

Feed one QUIC STREAM frame, by offset.

Bytes reach the h3 readers in order, once each; FIN is signalled
only when every byte up to the final size has arrived. Frames
for a request stream already answered are dropped. Uni streams
go to :meth:`feed_uni_stream_chunk`, bidi streams to
:meth:`feed_stream_chunk` and :meth:`signal_end_of_stream`.

#### `delivered_offset`

```mojo
def delivered_offset(self, stream_id: Int) -> UInt64
```

Bytes of ``stream_id`` delivered in order so far (0 for a stream not seen).

#### `has_stream`

```mojo
def has_stream(self, stream_id: Int) -> Bool
```

Whether the driver currently tracks a carrier for this stream ID. Useful for testing the open / close lifecycle without needing the full reactor.

#### `active_request_count`

```mojo
def active_request_count(self) -> Int
```

Number of active per-stream carriers. The reactor uses this to decide when to emit GOAWAY (above ``goaway_threshold_streams``).

#### `stream_has_headers`

```mojo
def stream_has_headers(self, stream_id: Int) -> Bool
```

Whether the first HEADERS frame has been fully parsed on ``stream_id``. The reactor checks this to decide when a stream is ready for handler dispatch (HEADERS alone is enough for a GET; DATA + FIN is required for methods with a body).

#### `stream_fin_received`

```mojo
def stream_fin_received(self, stream_id: Int) -> Bool
```

Whether the QUIC layer has signalled FIN on ``stream_id``. Set via :meth:`signal_end_of_stream`.

#### `stream_protocol_error`

```mojo
def stream_protocol_error(self, stream_id: Int) -> String
```

Per-stream protocol-error message; empty when the reader has not hit a protocol error.

#### `feed_stream_chunk`

```mojo
def feed_stream_chunk(mut self, stream_id: Int, var chunk: List[UInt8])
```

Feed a reassembled stream-data chunk into the per- stream reader.

Idempotently allocates the stream's carrier if it isn't
tracked yet (a chunk arriving for an unseen bidi stream
is the open-stream signal). Appends the chunk to the
per-stream inbox, then drains the inbox one frame at a
time via :func:`feed_into`. Each frame's callback fires
through a transient :class:`_Http3EventCollector`; the
collector's contents are merged into the per-stream
accumulator after the call returns.

Returns when either:

* ``feed_into`` returns NEEDS_MORE (the inbox doesn't
  yet hold a complete next frame).
* The reader transitions to ``DONE`` (trailers fired,
  protocol error, or stream-level shutdown).

#### `signal_end_of_stream`

```mojo
def signal_end_of_stream(mut self, stream_id: Int)
```

Signal that the QUIC layer observed FIN on ``stream_id``. The reader's sans-I/O frame state has no FIN signal of its own, so the reactor must inform the H3 driver via this method when the last STREAM frame on the request side carries the FIN bit. Used by the reactor to decide when a request-with-body has been fully reassembled.

#### `take_completed_streams`

```mojo
def take_completed_streams(self) -> List[Int]
```

Return the IDs of streams that have a request ready for handler dispatch.

A stream is ready when:

* The first HEADERS frame has been fully parsed
  (``headers_complete=True``), AND
* Either the request has no body (FIN observed) or the
  reader has reached DONE (trailers fired), AND
* The reactor has not already pulled this request via
  :meth:`take_request`, AND
* No protocol error has fired on the stream.

#### `take_request`

```mojo
def take_request(mut self, stream_id: Int) -> Request
```

Assemble + return the :class:`Request` for ``stream_id``. Idempotent guard: subsequent calls on the same stream raise so the reactor can't accidentally dispatch the same request through a Handler twice.

#### `is_tunnel`

```mojo
def is_tunnel(self, stream_id: Int) -> Bool
```

Whether ``stream_id`` carries an extended CONNECT request.

#### `body_backlog`

```mojo
def body_backlog(self, stream_id: Int) -> Int
```

Body bytes of a streamed request received and not yet read by its handler; -1 when the stream has no body being streamed.

#### `take_stream_body`

```mojo
def take_stream_body(mut self, stream_id: Int) -> List[UInt8]
```

The DATA payload bytes received on ``stream_id`` since the request (or the last call) took them: an extended CONNECT tunnel's inbound bytes.

#### `emit_response`

```mojo
def emit_response(mut self, stream_id: Int, var response: ResponseImpl)
```

Encode ``response`` into the per-stream outbox so the reactor can drain it via :meth:`take_response_frames`.

Emits HEADERS + (zero or more) DATA frames. Trailers
and the FIN bit are handled by the reactor (FIN is a
QUIC-level signal); this method only buffers the H3
frame bytes. Idempotent guard: emitting twice for the
same stream raises so the reactor can't accidentally
write a stale response after the stream is finalized.

#### `feed_uni_stream_chunk`

```mojo
def feed_uni_stream_chunk(mut self, stream_id: Int, var chunk: List[UInt8])
```

Feed reassembled bytes from a peer-initiated unidirectional QUIC stream into the H3 driver.

The first varint on each uni stream is the stream-type
codepoint (RFC 9114 §6.2). Once resolved, the driver
dispatches subsequent bytes to the matching state
machine:

* 0x00 (Control) -- parses SETTINGS first, then
  GOAWAY / MAX_PUSH_ID over the stream's lifetime.
* 0x01 (Push) -- refused: only a server opens push streams,
  so a client's is ``H3_STREAM_CREATION_ERROR`` (RFC 9114
  §6.2.2).
* 0x02 (QPACK encoder) -- replayed into the connection
  dynamic table via
  :meth:`_feed_peer_qpack_encoder_stream`; each insert
  owes an Insert Count Increment back on our decoder
  stream (drained by :meth:`take_qpack_decoder_frames`).
* 0x03 (QPACK decoder) -- captured but unused (we emit
  only static-table field sections, so the peer never
  acknowledges dynamic inserts to us).

A second QPACK encoder or decoder stream is
``H3_STREAM_CREATION_ERROR`` (RFC 9204 §4.2), like a second
control stream.

The stream-type varint may span multiple chunks (it is
at most 8 bytes per RFC 9000 §16). The driver buffers
until the type is resolvable + drains the buffer once
resolution succeeds.

#### `take_qpack_decoder_frames`

```mojo
def take_qpack_decoder_frames(mut self) -> List[UInt8]
```

Drain the QPACK decoder-stream bytes the connection owes the peer: an Insert Count Increment covering every encoder-stream insert applied since the last drain (RFC 9204 section 4.4.3). Returns empty when nothing is pending.

The default config advertises ``qpack_max_table_capacity
= 0``, so a conforming peer never streams dynamic inserts and this
never has anything to drain. Routing the drained bytes onto a
locally-opened QPACK decoder uni-stream is the reactor-side
upgrade path, gated on advertising a non-zero capacity. Section
Acknowledgment / Stream Cancellation are likewise deferred -- with
our static-only encoder the peer never blocks on them.

#### `emit_initial_settings`

```mojo
def emit_initial_settings(self) -> List[UInt8]
```

Build the server's outbound control-stream prefix: the stream-type varint (0x00) followed by a SETTINGS frame carrying the local :class:`Http3Config` values.

The reactor sends these bytes as the very first payload of the
server's control stream (RFC 9114 §6.2.1: SETTINGS MUST be the
first frame); :meth:`take_control_stream_start` is the
once-only form it calls. This is the only frame the server is
required to send proactively; GOAWAY / MAX_PUSH_ID are emitted
on demand.

#### `take_control_stream_start`

```mojo
def take_control_stream_start(mut self) -> List[UInt8]
```

The bytes to send at offset 0 of the server's control stream (:data:`H3_SERVER_CONTROL_STREAM_ID`): stream type 0x00 and the SETTINGS frame (RFC 9114 sections 6.2.1, 7.2.4). Returns them once; every later call returns an empty list. Also records :attr:`control_stream_id`.

The QUIC reactor calls this with the first 1-RTT flight, so the
control stream is initiated at the beginning of the connection
(H3-07: it was never opened, and the client never received the
server's SETTINGS).

#### `emit_goaway`

```mojo
def emit_goaway(mut self, max_stream_id: UInt64) -> List[UInt8]
```

Build a GOAWAY frame announcing ``max_stream_id`` (RFC 9114 §5.2). The reactor writes the result onto the locally-opened control stream immediately and flips :attr:`goaway_emitted` so the next open_request_stream rejects with H3_REQUEST_CANCELLED.

#### `take_response_frames`

```mojo
def take_response_frames(mut self, stream_id: Int) -> List[UInt8]
```

Drain pending outbound bytes for ``stream_id`` and return them to the reactor for emission as QUIC stream- data. Returns an empty list when nothing is queued. The reactor calls this repeatedly until it returns empty; each call is destructive (drained bytes are not held for re-reads).

## Functions

### `h3_error_code`

```mojo
def h3_error_code(message: String) -> UInt64
```

The HTTP/3 / QPACK error code (RFC 9114 section 8.1, RFC 9204 section 6) named by an error ``message``, or :data:`H3_GENERAL_PROTOCOL_ERROR` when it names none.

The driver raises ``Error`` with the code's name in the text
(``"H3_FRAME_UNEXPECTED: ..."``); the QUIC layer maps that to the
CONNECTION_CLOSE error code through this function.

## Aliases

### `H3_SERVER_CONTROL_STREAM_ID`

```mojo
comptime H3_SERVER_CONTROL_STREAM_ID = Int(3)
```

QUIC stream id of the server's control stream: the first server-initiated unidirectional stream (RFC 9000 section 2.1, ``0b11``).

### `H3_GENERAL_PROTOCOL_ERROR`

```mojo
comptime H3_GENERAL_PROTOCOL_ERROR = UInt64(257)
```

RFC 9114 section 8.1: the default code for an error with no more specific H3 code.

### `H3_STREAM_CREATION_ERROR`

```mojo
comptime H3_STREAM_CREATION_ERROR = UInt64(259)
```

### `H3_CLOSED_CRITICAL_STREAM`

```mojo
comptime H3_CLOSED_CRITICAL_STREAM = UInt64(260)
```

### `H3_FRAME_UNEXPECTED`

```mojo
comptime H3_FRAME_UNEXPECTED = UInt64(261)
```

### `H3_FRAME_ERROR`

```mojo
comptime H3_FRAME_ERROR = UInt64(262)
```

### `H3_EXCESSIVE_LOAD`

```mojo
comptime H3_EXCESSIVE_LOAD = UInt64(263)
```

### `H3_SETTINGS_ERROR`

```mojo
comptime H3_SETTINGS_ERROR = UInt64(265)
```

### `H3_MISSING_SETTINGS`

```mojo
comptime H3_MISSING_SETTINGS = UInt64(266)
```

### `H3_DATAGRAM_ERROR`

```mojo
comptime H3_DATAGRAM_ERROR = UInt64(51)
```

RFC 9297 sec 2.1: a malformed HTTP Datagram.

### `QPACK_DECOMPRESSION_FAILED`

```mojo
comptime QPACK_DECOMPRESSION_FAILED = UInt64(512)
```

RFC 9204 section 6.

### `QPACK_ENCODER_STREAM_ERROR`

```mojo
comptime QPACK_ENCODER_STREAM_ERROR = UInt64(513)
```

### `QPACK_DECODER_STREAM_ERROR`

```mojo
comptime QPACK_DECODER_STREAM_ERROR = UInt64(514)
```
