use frame::{util, Frame, Head, Error, StreamId, Kind}; use bytes::{BufMut, Bytes, Buf}; #[derive(Debug)] pub struct Data { stream_id: StreamId, data: T, flags: DataFlag, pad_len: Option, } #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub struct DataFlag(u8); const END_STREAM: u8 = 0x1; const PADDED: u8 = 0x8; const ALL: u8 = END_STREAM | PADDED; impl Data { pub fn load(head: Head, mut payload: Bytes) -> Result { let flags = DataFlag::load(head.flag()); let pad_len = if flags.is_padded() { let len = try!(util::strip_padding(&mut payload)); Some(len) } else { None }; Ok(Data { stream_id: head.stream_id(), data: payload, flags: flags, pad_len: pad_len, }) } } impl Data { pub fn stream_id(&self) -> StreamId { self.stream_id } pub fn is_end_stream(&self) -> bool { self.flags.is_end_stream() } pub fn set_end_stream(&mut self) { self.flags.set_end_stream(); } pub fn unset_end_stream(&mut self) { self.flags.unset_end_stream(); } pub fn head(&self) -> Head { Head::new(Kind::Data, self.flags.into(), self.stream_id) } pub fn payload(&self) -> &T { &self.data } pub fn payload_mut(&mut self) -> &mut T { &mut self.data } pub fn into_payload(self) -> T { self.data } pub fn map(self, f: F) -> Data where F: FnOnce(T) -> U, { Data { stream_id: self.stream_id, data: f(self.data), flags: self.flags, pad_len: self.pad_len, } } } impl Data { pub fn from_buf(stream_id: StreamId, data: T, eos: bool) -> Self { // TODO ensure that data.remaining() < MAX_FRAME_SIZE let mut flags = DataFlag::default(); if eos { flags.set_end_stream(); } Data { stream_id, data, flags, pad_len: None, } } pub fn encode_chunk(&mut self, dst: &mut U) { let len = self.data.remaining() as usize; if len > dst.remaining_mut() { unimplemented!(); } self.head().encode(len, dst); dst.put(&mut self.data); } } impl From> for Frame { fn from(src: Data) -> Self { Frame::Data(src) } } // ===== impl DataFlag ===== impl DataFlag { pub fn load(bits: u8) -> DataFlag { DataFlag(bits & ALL) } pub fn end_stream() -> DataFlag { DataFlag(END_STREAM) } pub fn padded() -> DataFlag { DataFlag(PADDED) } pub fn is_end_stream(&self) -> bool { self.0 & END_STREAM == END_STREAM } pub fn set_end_stream(&mut self) { self.0 |= END_STREAM } pub fn unset_end_stream(&mut self) { self.0 &= !END_STREAM } pub fn is_padded(&self) -> bool { self.0 & PADDED == PADDED } } impl Default for DataFlag { /// Returns a `HeadersFlag` value with `END_HEADERS` set. fn default() -> Self { DataFlag(0) } } impl From for u8 { fn from(src: DataFlag) -> u8 { src.0 } }