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 = DataFlags::load(bits: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: Option = if flags.is_padded() {
129 let len: u8 = 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
144impl<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.
150 pub(crate) fn encode_chunk<U: BufMut>(&mut self, dst: &mut U) {
151 let len: usize = self.data.remaining();
152
153 assert!(dst.remaining_mut() >= len);
154
155 self.head().encode(payload_len:len, dst);
156 dst.put(&mut self.data);
157 }
158}
159
160impl<T> From<Data<T>> for Frame<T> {
161 fn from(src: Data<T>) -> Self {
162 Frame::Data(src)
163 }
164}
165
166impl<T> fmt::Debug for Data<T> {
167 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
168 let mut f: DebugStruct<'_, '_> = fmt.debug_struct(name:"Data");
169 f.field(name:"stream_id", &self.stream_id);
170 if !self.flags.is_empty() {
171 f.field(name:"flags", &self.flags);
172 }
173 if let Some(ref pad_len: &u8) = self.pad_len {
174 f.field(name:"pad_len", value:pad_len);
175 }
176 // `data` bytes purposefully excluded
177 f.finish()
178 }
179}
180
181// ===== impl DataFlags =====
182
183impl DataFlags {
184 fn load(bits: u8) -> DataFlags {
185 DataFlags(bits & ALL)
186 }
187
188 fn is_empty(&self) -> bool {
189 self.0 == 0
190 }
191
192 fn is_end_stream(&self) -> bool {
193 self.0 & END_STREAM == END_STREAM
194 }
195
196 fn set_end_stream(&mut self) {
197 self.0 |= END_STREAM
198 }
199
200 fn unset_end_stream(&mut self) {
201 self.0 &= !END_STREAM
202 }
203
204 fn is_padded(&self) -> bool {
205 self.0 & PADDED == PADDED
206 }
207
208 #[cfg(feature = "unstable")]
209 fn set_padded(&mut self) {
210 self.0 |= PADDED
211 }
212}
213
214impl From<DataFlags> for u8 {
215 fn from(src: DataFlags) -> u8 {
216 src.0
217 }
218}
219
220impl fmt::Debug for DataFlags {
221 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
222 util&mut DebugFlags<'_, '_>::debug_flags(fmt, self.0)
223 .flag_if(self.is_end_stream(), "END_STREAM")
224 .flag_if(self.is_padded(), name:"PADDED")
225 .finish()
226 }
227}
228