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