Skip to main content

h2/frame/
data.rs

1use crate::frame::{util, Error, Frame, Head, Kind, StreamId};
2use bytes::{Buf, BufMut, Bytes};
3
4use 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)]
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    /// Creates a new DATA frame.
28    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.
42    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).
53    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.
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")]
68    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")]
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.
82    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.
90    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.
98    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        // 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    pub(crate) fn flow_controlled_len(&self) -> usize {
144        if let Some(pad_len) = self.pad_len {
145            // if PADDED, pad length field counts too (the + 1)
146            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        // Regression: the old padded_len() returned u8, so pad_len=255
182        // caused 255u8 + 1 = 0. The correct overhead is 256.
183        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    /// Encode the data frame into the `dst` buffer.
197    ///
198    /// # Panics
199    ///
200    /// Panics if `dst` cannot contain the data frame.
201    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        // `data` bytes purposefully excluded
228        f.finish()
229    }
230}
231
232// ===== impl DataFlags =====
233
234impl 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}