Skip to main content

ntex_h2/frame/
data.rs

1use ntex_bytes::{Bytes, BytesMut};
2
3use crate::frame::{Frame, FrameError, Head, Kind, StreamId, util};
4
5/// Data frame
6///
7/// Data frames convey arbitrary, variable-length sequences of octets associated
8/// with a stream. One or more DATA frames are used, for instance, to carry HTTP
9/// request or response payloads.
10#[derive(Clone, Eq, PartialEq)]
11pub struct Data {
12    stream_id: StreamId,
13    payload: Bytes,
14    flags: DataFlags,
15}
16
17#[derive(Default, Copy, Clone, Eq, PartialEq)]
18struct DataFlags(u8);
19
20const END_STREAM: u8 = 0x1;
21const PADDED: u8 = 0x8;
22const ALL: u8 = END_STREAM | PADDED;
23
24impl Data {
25    /// Creates a new DATA frame.
26    ///
27    /// # Panics
28    ///
29    /// Panics if stream id is zero
30    pub fn new(stream_id: StreamId, payload: Bytes) -> Self {
31        assert!(!stream_id.is_zero());
32
33        Data {
34            payload,
35            stream_id,
36            flags: DataFlags::default(),
37        }
38    }
39
40    /// Returns the stream identifier that this frame is associated with.
41    ///
42    /// This cannot be a zero stream identifier.
43    pub fn stream_id(&self) -> StreamId {
44        self.stream_id
45    }
46
47    /// Gets the value of the `END_STREAM` flag for this frame.
48    ///
49    /// If true, this frame is the last that the endpoint will send for the
50    /// identified stream.
51    ///
52    /// Setting this flag causes the stream to enter one of the "half-closed"
53    /// states or the "closed" state (Section 5.1).
54    pub fn is_end_stream(&self) -> bool {
55        self.flags.is_end_stream()
56    }
57
58    /// Sets the value for the `END_STREAM` flag on this frame.
59    pub fn set_end_stream(&mut self) {
60        self.flags.set_end_stream();
61    }
62
63    /// Returns whether the `PADDED` flag is set on this frame.
64    pub fn is_padded(&self) -> bool {
65        self.flags.is_padded()
66    }
67
68    /// Sets the value for the `PADDED` flag on this frame.
69    pub fn set_padded(&mut self) {
70        self.flags.set_padded();
71    }
72
73    /// Returns a reference to this frame's payload.
74    ///
75    /// This does **not** include any padding that might have been originally
76    /// included.
77    pub fn payload(&self) -> &Bytes {
78        &self.payload
79    }
80
81    /// Returns a mutable reference to this frame's payload.
82    ///
83    /// This does **not** include any padding that might have been originally
84    /// included.
85    pub fn payload_mut(&mut self) -> &mut Bytes {
86        &mut self.payload
87    }
88
89    /// Consumes `self` and returns the frame's payload.
90    ///
91    /// This does **not** include any padding that might have been originally
92    /// included.
93    pub fn into_payload(self) -> Bytes {
94        self.payload
95    }
96
97    pub(crate) fn head(&self) -> Head {
98        Head::new(Kind::Data, self.flags.into(), self.stream_id)
99    }
100
101    pub(crate) fn load(head: Head, mut payload: Bytes) -> Result<Self, FrameError> {
102        let flags = DataFlags::load(head.flag());
103
104        // The stream identifier must not be zero
105        if head.stream_id().is_zero() {
106            return Err(FrameError::InvalidStreamId);
107        }
108
109        if flags.is_padded() {
110            util::strip_padding(&mut payload)?;
111        }
112
113        Ok(Data {
114            flags,
115            payload,
116            stream_id: head.stream_id(),
117        })
118    }
119
120    /// Encode the data frame into the `dst` buffer.
121    pub(crate) fn encode(&self, dst: &mut BytesMut) {
122        // Encode the frame head to the buffer
123        self.head().encode(self.payload.len(), dst);
124        // Encode payload
125        dst.extend_from_slice(&self.payload);
126    }
127}
128
129impl From<Data> for Frame {
130    fn from(src: Data) -> Self {
131        Frame::Data(src)
132    }
133}
134
135impl std::fmt::Debug for Data {
136    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        let mut f = fmt.debug_struct("Data");
138        f.field("stream_id", &self.stream_id);
139        f.field("data_len", &self.payload.len());
140        if !self.flags.is_empty() {
141            f.field("flags", &self.flags);
142        }
143        // `data` bytes purposefully excluded
144        f.finish()
145    }
146}
147
148// ===== impl DataFlags =====
149
150impl DataFlags {
151    fn load(bits: u8) -> DataFlags {
152        DataFlags(bits & ALL)
153    }
154
155    fn is_empty(self) -> bool {
156        self.0 == 0
157    }
158
159    fn is_end_stream(self) -> bool {
160        self.0 & END_STREAM == END_STREAM
161    }
162
163    fn set_end_stream(&mut self) {
164        self.0 |= END_STREAM;
165    }
166
167    fn is_padded(self) -> bool {
168        self.0 & PADDED == PADDED
169    }
170
171    fn set_padded(&mut self) {
172        self.0 |= PADDED;
173    }
174}
175
176impl From<DataFlags> for u8 {
177    fn from(src: DataFlags) -> u8 {
178        src.0
179    }
180}
181
182impl std::fmt::Debug for DataFlags {
183    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184        util::debug_flags(fmt, self.0)
185            .flag_if(self.is_end_stream(), "END_STREAM")
186            .flag_if(self.is_padded(), "PADDED")
187            .finish()
188    }
189}