use thiserror::Error;
use crate::{
sid::{be_streamid, StreamId, WriteStreamId},
varint::{be_varint, VarInt, WriteVarInt},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ResetStreamFrame {
pub stream_id: StreamId,
pub app_error_code: VarInt,
pub final_size: VarInt,
}
const RESET_STREAM_FRAME_TYPE: u8 = 0x04;
impl super::BeFrame for ResetStreamFrame {
fn frame_type(&self) -> super::FrameType {
super::FrameType::ResetStream
}
fn max_encoding_size(&self) -> usize {
1 + 8 + 8 + 8
}
fn encoding_size(&self) -> usize {
1 + self.stream_id.encoding_size()
+ self.app_error_code.encoding_size()
+ self.final_size.encoding_size()
}
}
pub fn be_reset_stream_frame(input: &[u8]) -> nom::IResult<&[u8], ResetStreamFrame> {
use nom::{combinator::map, sequence::tuple};
map(
tuple((be_streamid, be_varint, be_varint)),
|(stream_id, app_error_code, final_size)| ResetStreamFrame {
stream_id,
app_error_code,
final_size,
},
)(input)
}
impl<T: bytes::BufMut> super::io::WriteFrame<ResetStreamFrame> for T {
fn put_frame(&mut self, frame: &ResetStreamFrame) {
self.put_u8(RESET_STREAM_FRAME_TYPE);
self.put_streamid(&frame.stream_id);
self.put_varint(&frame.app_error_code);
self.put_varint(&frame.final_size);
}
}
#[derive(Clone, Copy, Debug, Error)]
#[error("the stream was reset with app error code: {app_error_code}, final size: {final_size}")]
pub struct ResetStreamError {
app_error_code: VarInt,
final_size: VarInt,
}
impl ResetStreamError {
pub fn new(app_error_code: VarInt, final_size: VarInt) -> Self {
Self {
app_error_code,
final_size,
}
}
pub fn error_code(&self) -> u64 {
self.app_error_code.into_inner()
}
pub fn combine(self, sid: StreamId) -> ResetStreamFrame {
ResetStreamFrame {
stream_id: sid,
app_error_code: self.app_error_code,
final_size: self.final_size,
}
}
}
impl From<&ResetStreamFrame> for ResetStreamError {
fn from(frame: &ResetStreamFrame) -> Self {
Self {
app_error_code: frame.app_error_code,
final_size: frame.final_size,
}
}
}
#[cfg(test)]
mod tests {
use nom::combinator::flat_map;
use super::{ResetStreamFrame, RESET_STREAM_FRAME_TYPE};
use crate::{
frame::io::WriteFrame,
varint::{be_varint, VarInt},
};
#[test]
fn test_read_reset_stream_frame() {
let buf = vec![
RESET_STREAM_FRAME_TYPE,
0x52,
0x34,
0x80,
0,
0x56,
0x78,
0x80,
0,
0x9a,
0xbc,
];
let (input, frame) = flat_map(be_varint, |frame_type| {
if frame_type.into_inner() == RESET_STREAM_FRAME_TYPE as u64 {
super::be_reset_stream_frame
} else {
panic!("wrong frame type: {}", frame_type)
}
})(buf.as_ref())
.unwrap();
assert!(input.is_empty());
assert_eq!(
frame,
ResetStreamFrame {
stream_id: VarInt::from_u32(0x1234).into(),
app_error_code: VarInt::from_u32(0x5678),
final_size: VarInt::from_u32(0x9abc),
}
);
}
#[test]
fn test_write_reset_stream_frame() {
let mut buf = Vec::new();
buf.put_frame(&ResetStreamFrame {
stream_id: VarInt::from_u32(0x1234).into(),
app_error_code: VarInt::from_u32(0x5678),
final_size: VarInt::from_u32(0x9abc),
});
assert_eq!(
buf,
vec![
RESET_STREAM_FRAME_TYPE,
0x52,
0x34,
0x80,
0,
0x56,
0x78,
0x80,
0,
0x9a,
0xbc
]
);
}
}