1use crate::frame::{util, Error, Frame, Head, Kind, StreamId};
2use bytes::{Buf, BufMut, Bytes};
3
4use std::fmt;
5
6#[derive(Eq, PartialEq)]
12pub 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, Default, Eq, PartialEq)]
20struct DataFlags(u8);
21
22const END_STREAM: u8 = 0x1;
23const PADDED: u8 = 0x8;
24const ALL: u8 = END_STREAM | PADDED;
25
26impl<T> Data<T> {
27 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 pub fn stream_id(&self) -> StreamId {
43 self.stream_id
44 }
45
46 pub fn is_end_stream(&self) -> bool {
54 self.flags.is_end_stream()
55 }
56
57 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 #[cfg(feature = "unstable")]
68 pub fn is_padded(&self) -> bool {
69 self.flags.is_padded()
70 }
71
72 #[cfg(feature = "unstable")]
74 pub fn set_padded(&mut self) {
75 self.flags.set_padded();
76 }
77
78 pub fn payload(&self) -> &T {
83 &self.data
84 }
85
86 pub fn payload_mut(&mut self) -> &mut T {
91 &mut self.data
92 }
93
94 pub fn into_payload(self) -> T {
99 self.data
100 }
101
102 pub(crate) fn head(&self) -> Head {
103 Head::new(Kind::Data, self.flags.into(), self.stream_id)
104 }
105
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
119impl Data<Bytes> {
120 pub(crate) fn load(head: Head, mut payload: Bytes) -> Result<Self, Error> {
121 let flags = DataFlags::load(head.flag());
122
123 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 pub(crate) fn flow_controlled_len(&self) -> usize {
144 if let Some(pad_len) = self.pad_len {
145 self.data.len() + usize::from(pad_len) + 1
147 } else {
148 self.data.len()
149 }
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use bytes::Bytes;
157
158 fn data_frame(data: &[u8], pad_len: Option<u8>) -> Data<Bytes> {
159 Data {
160 stream_id: StreamId::from(1),
161 data: Bytes::copy_from_slice(data),
162 flags: DataFlags::default(),
163 pad_len,
164 }
165 }
166
167 #[test]
168 fn padding_overhead_no_padding() {
169 let frame = data_frame(b"hello", None);
170 assert_eq!(frame.flow_controlled_len() - frame.payload().len(), 0);
171 }
172
173 #[test]
174 fn padding_overhead_small() {
175 let frame = data_frame(b"hello", Some(10));
176 assert_eq!(frame.flow_controlled_len() - frame.payload().len(), 11);
177 }
178
179 #[test]
180 fn padding_overhead_max_does_not_overflow() {
181 let frame = data_frame(b"", Some(255));
184 assert_eq!(frame.flow_controlled_len() - frame.payload().len(), 256);
185 }
186
187 #[test]
188 fn padding_overhead_max_with_data() {
189 let frame = data_frame(b"hello", Some(255));
190 assert_eq!(frame.flow_controlled_len() - frame.payload().len(), 256);
191 assert_eq!(frame.flow_controlled_len(), 261);
192 }
193}
194
195impl<T: Buf> Data<T> {
196 pub(crate) fn encode_chunk<U: BufMut>(&mut self, dst: &mut U) {
202 let len = self.data.remaining();
203
204 assert!(dst.remaining_mut() >= len);
205
206 self.head().encode(len, dst);
207 dst.put(&mut self.data);
208 }
209}
210
211impl<T> From<Data<T>> for Frame<T> {
212 fn from(src: Data<T>) -> Self {
213 Frame::Data(src)
214 }
215}
216
217impl<T> fmt::Debug for Data<T> {
218 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
219 let mut f = fmt.debug_struct("Data");
220 f.field("stream_id", &self.stream_id);
221 if !self.flags.is_empty() {
222 f.field("flags", &self.flags);
223 }
224 if let Some(ref pad_len) = self.pad_len {
225 f.field("pad_len", pad_len);
226 }
227 f.finish()
229 }
230}
231
232impl DataFlags {
235 fn load(bits: u8) -> DataFlags {
236 DataFlags(bits & ALL)
237 }
238
239 fn is_empty(&self) -> bool {
240 self.0 == 0
241 }
242
243 fn is_end_stream(&self) -> bool {
244 self.0 & END_STREAM == END_STREAM
245 }
246
247 fn set_end_stream(&mut self) {
248 self.0 |= END_STREAM
249 }
250
251 fn unset_end_stream(&mut self) {
252 self.0 &= !END_STREAM
253 }
254
255 fn is_padded(&self) -> bool {
256 self.0 & PADDED == PADDED
257 }
258
259 #[cfg(feature = "unstable")]
260 fn set_padded(&mut self) {
261 self.0 |= PADDED
262 }
263}
264
265impl From<DataFlags> for u8 {
266 fn from(src: DataFlags) -> u8 {
267 src.0
268 }
269}
270
271impl fmt::Debug for DataFlags {
272 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
273 util::debug_flags(fmt, self.0)
274 .flag_if(self.is_end_stream(), "END_STREAM")
275 .flag_if(self.is_padded(), "PADDED")
276 .finish()
277 }
278}