use super::{read_first_byte, read_varint};
use crate::{
h3::{H3Error, H3ErrorCode},
headers::integer_prefix,
};
use futures_lite::io::AsyncRead;
const SECTION_ACK: u8 = 0x80;
const STREAM_CANCEL: u8 = 0x40;
const INSERT_COUNT_INC: u8 = 0x00;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::headers) enum DecoderInstruction {
SectionAcknowledgement { stream_id: u64 },
StreamCancellation { stream_id: u64 },
InsertCountIncrement { increment: u64 },
}
pub(in crate::headers) async fn parse(
stream: &mut (impl AsyncRead + Unpin),
) -> Result<Option<DecoderInstruction>, H3Error> {
parse_inner(stream)
.await
.map_err(|()| H3ErrorCode::QpackDecoderStreamError.into())
}
async fn parse_inner(
stream: &mut (impl AsyncRead + Unpin),
) -> Result<Option<DecoderInstruction>, ()> {
let Some(first) = read_first_byte(stream).await? else {
return Ok(None);
};
let instr = if first & SECTION_ACK != 0 {
let stream_id = read_varint(first, 7, stream).await? as u64;
DecoderInstruction::SectionAcknowledgement { stream_id }
} else if first & STREAM_CANCEL != 0 {
let stream_id = read_varint(first, 6, stream).await? as u64;
DecoderInstruction::StreamCancellation { stream_id }
} else {
let increment = read_varint(first, 6, stream).await? as u64;
DecoderInstruction::InsertCountIncrement { increment }
};
Ok(Some(instr))
}
pub(in crate::headers) fn encode_section_ack(stream_id: u64, buf: &mut Vec<u8>) {
let start = buf.len();
integer_prefix::encode_into(usize::try_from(stream_id).unwrap_or(usize::MAX), 7, buf);
buf[start] |= SECTION_ACK;
}
pub(in crate::headers) fn encode_insert_count_increment(increment: u64, buf: &mut Vec<u8>) {
let start = buf.len();
integer_prefix::encode_into(usize::try_from(increment).unwrap_or(usize::MAX), 6, buf);
buf[start] |= INSERT_COUNT_INC; }