use crate::error::QpackError;
use super::integer;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecoderInstruction {
SectionAcknowledgment { stream_id: u64 },
StreamCancellation { stream_id: u64 },
InsertCountIncrement { increment: u64 },
}
#[derive(Debug)]
pub struct DecoderStream {
send_buffer: Vec<u8>,
}
impl Default for DecoderStream {
fn default() -> Self {
Self::new()
}
}
impl DecoderStream {
pub fn new() -> Self {
Self {
send_buffer: Vec::new(),
}
}
pub fn write_stream_type(&mut self) {
self.send_buffer.push(0x03);
}
pub fn encode_section_acknowledgment(&mut self, stream_id: u64) {
integer::encode_integer_to_vec(&mut self.send_buffer, stream_id, 7, 0x80);
}
pub fn encode_stream_cancellation(&mut self, stream_id: u64) {
integer::encode_integer_to_vec(&mut self.send_buffer, stream_id, 6, 0x40);
}
pub fn encode_insert_count_increment(&mut self, increment: u64) {
integer::encode_integer_to_vec(&mut self.send_buffer, increment, 6, 0x00);
}
pub fn get_data(&self) -> &[u8] {
&self.send_buffer
}
pub fn consume_data(&mut self, len: usize) {
if len >= self.send_buffer.len() {
self.send_buffer.clear();
} else {
self.send_buffer.drain(..len);
}
}
pub fn has_pending(&self) -> bool {
!self.send_buffer.is_empty()
}
}
#[derive(Debug)]
pub struct DecoderStreamReceiver {
recv_buffer: Vec<u8>,
known_received_count: u64,
}
impl Default for DecoderStreamReceiver {
fn default() -> Self {
Self::new()
}
}
impl DecoderStreamReceiver {
pub fn new() -> Self {
Self {
recv_buffer: Vec::new(),
known_received_count: 0,
}
}
pub fn known_received_count(&self) -> u64 {
self.known_received_count
}
pub fn receive(&mut self, data: &[u8]) {
self.recv_buffer.extend_from_slice(data);
}
pub fn process(
&mut self,
total_insert_count: u64,
) -> Result<Option<DecoderInstruction>, QpackError> {
if self.recv_buffer.is_empty() {
return Ok(None);
}
let first = self.recv_buffer[0];
let result = if first & 0x80 != 0 {
self.decode_section_acknowledgment()
} else if first & 0x40 != 0 {
self.decode_stream_cancellation()
} else {
self.decode_insert_count_increment(total_insert_count)
};
match result {
Err(QpackError::BufferTooShort) => Ok(None),
other => other,
}
}
fn decode_section_acknowledgment(&mut self) -> Result<Option<DecoderInstruction>, QpackError> {
let (stream_id, consumed) = integer::decode_integer(&self.recv_buffer, 7)?;
self.recv_buffer.drain(..consumed);
Ok(Some(DecoderInstruction::SectionAcknowledgment {
stream_id,
}))
}
fn decode_stream_cancellation(&mut self) -> Result<Option<DecoderInstruction>, QpackError> {
let (stream_id, consumed) = integer::decode_integer(&self.recv_buffer, 6)?;
self.recv_buffer.drain(..consumed);
Ok(Some(DecoderInstruction::StreamCancellation { stream_id }))
}
fn decode_insert_count_increment(
&mut self,
total_insert_count: u64,
) -> Result<Option<DecoderInstruction>, QpackError> {
let (increment, consumed) = integer::decode_integer(&self.recv_buffer, 6)?;
if increment == 0 {
return Err(QpackError::DecodeFailed);
}
let new_known = self.known_received_count + increment;
if new_known > total_insert_count {
return Err(QpackError::DecodeFailed);
}
self.recv_buffer.drain(..consumed);
self.known_received_count = new_known;
Ok(Some(DecoderInstruction::InsertCountIncrement { increment }))
}
pub fn buffer(&self) -> &[u8] {
&self.recv_buffer
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_section_acknowledgment() {
let mut stream = DecoderStream::new();
stream.encode_section_acknowledgment(4);
assert_eq!(stream.get_data(), &[0x84]);
}
#[test]
fn test_encode_section_acknowledgment_large() {
let mut stream = DecoderStream::new();
stream.encode_section_acknowledgment(200);
assert_eq!(stream.get_data(), &[0xff, 73]);
}
#[test]
fn test_encode_stream_cancellation() {
let mut stream = DecoderStream::new();
stream.encode_stream_cancellation(8);
assert_eq!(stream.get_data(), &[0x48]);
}
#[test]
fn test_encode_insert_count_increment() {
let mut stream = DecoderStream::new();
stream.encode_insert_count_increment(3);
assert_eq!(stream.get_data(), &[0x03]);
}
#[test]
fn test_decode_insert_count_increment_zero() {
let mut receiver = DecoderStreamReceiver::new();
receiver.receive(&[0x00]);
let result = receiver.process(10);
assert!(result.is_err());
}
#[test]
fn test_decode_insert_count_increment_exceeds_total() {
let mut receiver = DecoderStreamReceiver::new();
receiver.receive(&[0x05]);
let result = receiver.process(3);
assert!(result.is_err());
assert_eq!(receiver.known_received_count(), 0);
}
#[test]
fn test_decode_insert_count_increment_valid() {
let mut receiver = DecoderStreamReceiver::new();
receiver.receive(&[0x03]);
let result = receiver.process(5).unwrap();
assert_eq!(
result,
Some(DecoderInstruction::InsertCountIncrement { increment: 3 })
);
assert_eq!(receiver.known_received_count(), 3);
}
}