use bytes::Bytes;
use crate::solicit::frame::builder::FrameBuilder;
use crate::solicit::frame::Frame;
use crate::solicit::frame::FrameHeader;
use crate::solicit::frame::FrameIR;
use crate::solicit::frame::ParseFrameError;
use crate::solicit::frame::ParseFrameResult;
use crate::solicit::frame::RawFrame;
use super::flags::Flag;
use super::flags::Flags;
use crate::codec::write_buffer::WriteBuffer;
use crate::solicit::stream_id::StreamId;
pub const CONTINUATION_FRAME_TYPE: u8 = 0x9;
#[derive(Clone, PartialEq, Debug, Copy)]
pub enum ContinuationFlag {
EndHeaders = 0x4,
}
impl Flag for ContinuationFlag {
#[inline]
fn bitmask(&self) -> u8 {
*self as u8
}
fn flags() -> &'static [Self] {
static FLAGS: &'static [ContinuationFlag] = &[ContinuationFlag::EndHeaders];
FLAGS
}
}
#[derive(PartialEq, Clone, Debug)]
pub struct ContinuationFrame {
pub flags: Flags<ContinuationFlag>,
pub stream_id: StreamId,
pub header_fragment: Bytes,
}
impl ContinuationFrame {
pub fn new(fragment: Bytes, stream_id: StreamId) -> ContinuationFrame {
ContinuationFrame {
header_fragment: fragment,
stream_id: stream_id,
flags: Flags::default(),
}
}
fn payload_len(&self) -> u32 {
self.header_fragment.len() as u32
}
pub fn is_headers_end(&self) -> bool {
self.flags.is_set(ContinuationFlag::EndHeaders)
}
pub fn set_flag(&mut self, flag: ContinuationFlag) {
self.flags.set(flag);
}
}
impl Frame for ContinuationFrame {
type FlagType = ContinuationFlag;
fn from_raw(raw_frame: &RawFrame) -> ParseFrameResult<ContinuationFrame> {
let FrameHeader {
payload_len,
frame_type,
flags,
stream_id,
} = raw_frame.header();
if frame_type != CONTINUATION_FRAME_TYPE {
return Err(ParseFrameError::InternalError);
}
if (payload_len as usize) != raw_frame.payload().len() {
return Err(ParseFrameError::InternalError);
}
if stream_id == 0 {
return Err(ParseFrameError::StreamIdMustBeNonZero);
}
Ok(ContinuationFrame {
header_fragment: raw_frame.payload(),
stream_id,
flags: Flags::new(flags),
})
}
fn flags(&self) -> Flags<ContinuationFlag> {
self.flags
}
fn get_stream_id(&self) -> StreamId {
self.stream_id
}
fn get_header(&self) -> FrameHeader {
FrameHeader {
payload_len: self.payload_len(),
frame_type: CONTINUATION_FRAME_TYPE,
flags: self.flags.0,
stream_id: self.stream_id,
}
}
}
impl FrameIR for ContinuationFrame {
fn serialize_into(self, b: &mut WriteBuffer) {
b.write_header(self.get_header());
b.extend_from_bytes(self.header_fragment);
}
}