// HTTP/3 unidirectional stream types (RFC 9114 §6.2, RFC 9204 §4.2). Every unidirectional
// stream opens with a variable-length integer naming its type: the control stream (0x00)
// that carries SETTINGS and connection-control frames, a server push stream (0x01) prefixed
// with its push id, and the QPACK encoder (0x02) and decoder (0x03) streams that carry the
// dynamic-table instructions. Unrecognized types are reserved/greased and their payloads are
// ignored (§6.2, §6.2.3). This is the demultiplexer a connection runs over the raw QUIC
// unidirectional streams before dispatching to the frame and QPACK-instruction codecs.
///|
/// An HTTP/3 unidirectional stream's type (RFC 9114 §6.2, RFC 9204 §4.2).
pub(all) enum Http3UniStream {
ControlStream
PushStream(UInt64)
QpackEncoderStream
QpackDecoderStream
ReservedStream(UInt64)
} derive(Eq, Debug)
///|
/// Encode a unidirectional stream's opening bytes: the type varint, plus the push id for a
/// push stream (RFC 9114 §6.2.2).
pub fn http3_encode_stream_type(stream : Http3UniStream) -> Bytes {
match stream {
ControlStream => quic_varint_encode(0x00)
PushStream(push_id) => {
let buf = Buffer()
buf.write_bytes(quic_varint_encode(0x01))
buf.write_bytes(quic_varint_encode(push_id))
buf.to_bytes()
}
QpackEncoderStream => quic_varint_encode(0x02)
QpackDecoderStream => quic_varint_encode(0x03)
ReservedStream(t) => quic_varint_encode(t)
}
}
///|
/// Decode a unidirectional stream's opening bytes: the type varint (and a push id for a push
/// stream). Returns the stream kind and bytes consumed, or `None` on a partial read.
pub fn http3_decode_stream_type(input : BytesView) -> (Http3UniStream, Int)? {
let (stream_type, type_len) = match quic_varint_decode(input) {
Some(v) => v
None => return None
}
match stream_type {
0x00 => Some((ControlStream, type_len))
0x01 =>
match quic_varint_decode(input[type_len:]) {
Some((push_id, id_len)) =>
Some((PushStream(push_id), type_len + id_len))
None => None
}
0x02 => Some((QpackEncoderStream, type_len))
0x03 => Some((QpackDecoderStream, type_len))
other => Some((ReservedStream(other), type_len))
}
}
///|
/// Encode a control stream (RFC 9114 §6.2.1): the control-stream type, then a SETTINGS frame
/// with `settings`, which a control stream must send first.
pub fn http3_encode_control_stream(settings : Array[(UInt64, UInt64)]) -> Bytes {
let buf = Buffer()
buf.write_bytes(http3_encode_stream_type(ControlStream))
buf.write_bytes(http3_frame_encode(Settings(settings)))
buf.to_bytes()
}