1 use crate::frame::{util, Error, Frame, Head, Kind, StreamId}; 2 use bytes::{Buf, BufMut, Bytes}; 3 4 use std::fmt; 5 6 /// Data frame 7 /// 8 /// Data frames convey arbitrary, variable-length sequences of octets associated 9 /// with a stream. One or more DATA frames are used, for instance, to carry HTTP 10 /// request or response payloads. 11 #[derive(Eq, PartialEq)] 12 pub struct Data<T = Bytes> { 13 stream_id: StreamId, 14 data: T, 15 flags: DataFlags, 16 pad_len: Option<u8>, 17 } 18 19 #[derive(Copy, Clone, Eq, PartialEq)] 20 struct DataFlags(u8); 21 22 const END_STREAM: u8 = 0x1; 23 const PADDED: u8 = 0x8; 24 const ALL: u8 = END_STREAM | PADDED; 25 26 impl<T> Data<T> { 27 /// Creates a new DATA frame. new(stream_id: StreamId, payload: T) -> Self28 pub fn new(stream_id: StreamId, payload: T) -> Self { 29 assert!(!stream_id.is_zero()); 30 31 Data { 32 stream_id, 33 data: payload, 34 flags: DataFlags::default(), 35 pad_len: None, 36 } 37 } 38 39 /// Returns the stream identifier that this frame is associated with. 40 /// 41 /// This cannot be a zero stream identifier. stream_id(&self) -> StreamId42 pub fn stream_id(&self) -> StreamId { 43 self.stream_id 44 } 45 46 /// Gets the value of the `END_STREAM` flag for this frame. 47 /// 48 /// If true, this frame is the last that the endpoint will send for the 49 /// identified stream. 50 /// 51 /// Setting this flag causes the stream to enter one of the "half-closed" 52 /// states or the "closed" state (Section 5.1). is_end_stream(&self) -> bool53 pub fn is_end_stream(&self) -> bool { 54 self.flags.is_end_stream() 55 } 56 57 /// Sets the value for the `END_STREAM` flag on this frame. set_end_stream(&mut self, val: bool)58 pub fn set_end_stream(&mut self, val: bool) { 59 if val { 60 self.flags.set_end_stream(); 61 } else { 62 self.flags.unset_end_stream(); 63 } 64 } 65 66 /// Returns whether the `PADDED` flag is set on this frame. 67 #[cfg(feature = "unstable")] is_padded(&self) -> bool68 pub fn is_padded(&self) -> bool { 69 self.flags.is_padded() 70 } 71 72 /// Sets the value for the `PADDED` flag on this frame. 73 #[cfg(feature = "unstable")] set_padded(&mut self)74 pub fn set_padded(&mut self) { 75 self.flags.set_padded(); 76 } 77 78 /// Returns a reference to this frame's payload. 79 /// 80 /// This does **not** include any padding that might have been originally 81 /// included. payload(&self) -> &T82 pub fn payload(&self) -> &T { 83 &self.data 84 } 85 86 /// Returns a mutable reference to this frame's payload. 87 /// 88 /// This does **not** include any padding that might have been originally 89 /// included. payload_mut(&mut self) -> &mut T90 pub fn payload_mut(&mut self) -> &mut T { 91 &mut self.data 92 } 93 94 /// Consumes `self` and returns the frame's payload. 95 /// 96 /// This does **not** include any padding that might have been originally 97 /// included. into_payload(self) -> T98 pub fn into_payload(self) -> T { 99 self.data 100 } 101 head(&self) -> Head102 pub(crate) fn head(&self) -> Head { 103 Head::new(Kind::Data, self.flags.into(), self.stream_id) 104 } 105 map<F, U>(self, f: F) -> Data<U> where F: FnOnce(T) -> U,106 pub(crate) fn map<F, U>(self, f: F) -> Data<U> 107 where 108 F: FnOnce(T) -> U, 109 { 110 Data { 111 stream_id: self.stream_id, 112 data: f(self.data), 113 flags: self.flags, 114 pad_len: self.pad_len, 115 } 116 } 117 } 118 119 impl Data<Bytes> { load(head: Head, mut payload: Bytes) -> Result<Self, Error>120 pub(crate) fn load(head: Head, mut payload: Bytes) -> Result<Self, Error> { 121 let flags = DataFlags::load(head.flag()); 122 123 // The stream identifier must not be zero 124 if head.stream_id().is_zero() { 125 return Err(Error::InvalidStreamId); 126 } 127 128 let pad_len = if flags.is_padded() { 129 let len = util::strip_padding(&mut payload)?; 130 Some(len) 131 } else { 132 None 133 }; 134 135 Ok(Data { 136 stream_id: head.stream_id(), 137 data: payload, 138 flags, 139 pad_len, 140 }) 141 } 142 } 143 144 impl<T: Buf> Data<T> { 145 /// Encode the data frame into the `dst` buffer. 146 /// 147 /// # Panics 148 /// 149 /// Panics if `dst` cannot contain the data frame. encode_chunk<U: BufMut>(&mut self, dst: &mut U)150 pub(crate) fn encode_chunk<U: BufMut>(&mut self, dst: &mut U) { 151 let len = self.data.remaining() as usize; 152 153 assert!(dst.remaining_mut() >= len); 154 155 self.head().encode(len, dst); 156 dst.put(&mut self.data); 157 } 158 } 159 160 impl<T> From<Data<T>> for Frame<T> { from(src: Data<T>) -> Self161 fn from(src: Data<T>) -> Self { 162 Frame::Data(src) 163 } 164 } 165 166 impl<T> fmt::Debug for Data<T> { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result167 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 168 let mut f = fmt.debug_struct("Data"); 169 f.field("stream_id", &self.stream_id); 170 if !self.flags.is_empty() { 171 f.field("flags", &self.flags); 172 } 173 if let Some(ref pad_len) = self.pad_len { 174 f.field("pad_len", pad_len); 175 } 176 // `data` bytes purposefully excluded 177 f.finish() 178 } 179 } 180 181 // ===== impl DataFlags ===== 182 183 impl DataFlags { load(bits: u8) -> DataFlags184 fn load(bits: u8) -> DataFlags { 185 DataFlags(bits & ALL) 186 } 187 is_empty(&self) -> bool188 fn is_empty(&self) -> bool { 189 self.0 == 0 190 } 191 is_end_stream(&self) -> bool192 fn is_end_stream(&self) -> bool { 193 self.0 & END_STREAM == END_STREAM 194 } 195 set_end_stream(&mut self)196 fn set_end_stream(&mut self) { 197 self.0 |= END_STREAM 198 } 199 unset_end_stream(&mut self)200 fn unset_end_stream(&mut self) { 201 self.0 &= !END_STREAM 202 } 203 is_padded(&self) -> bool204 fn is_padded(&self) -> bool { 205 self.0 & PADDED == PADDED 206 } 207 208 #[cfg(feature = "unstable")] set_padded(&mut self)209 fn set_padded(&mut self) { 210 self.0 |= PADDED 211 } 212 } 213 214 impl Default for DataFlags { default() -> Self215 fn default() -> Self { 216 DataFlags(0) 217 } 218 } 219 220 impl From<DataFlags> for u8 { from(src: DataFlags) -> u8221 fn from(src: DataFlags) -> u8 { 222 src.0 223 } 224 } 225 226 impl fmt::Debug for DataFlags { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result227 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 228 util::debug_flags(fmt, self.0) 229 .flag_if(self.is_end_stream(), "END_STREAM") 230 .flag_if(self.is_padded(), "PADDED") 231 .finish() 232 } 233 } 234