1use ntex_bytes::{Bytes, BytesMut};
2
3use crate::frame::{Frame, FrameError, Head, Kind, StreamId, util};
4
5#[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 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 pub fn stream_id(&self) -> StreamId {
44 self.stream_id
45 }
46
47 pub fn is_end_stream(&self) -> bool {
55 self.flags.is_end_stream()
56 }
57
58 pub fn set_end_stream(&mut self) {
60 self.flags.set_end_stream();
61 }
62
63 pub fn is_padded(&self) -> bool {
65 self.flags.is_padded()
66 }
67
68 pub fn set_padded(&mut self) {
70 self.flags.set_padded();
71 }
72
73 pub fn payload(&self) -> &Bytes {
78 &self.payload
79 }
80
81 pub fn payload_mut(&mut self) -> &mut Bytes {
86 &mut self.payload
87 }
88
89 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 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 pub(crate) fn encode(&self, dst: &mut BytesMut) {
122 self.head().encode(self.payload.len(), dst);
124 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 f.finish()
145 }
146}
147
148impl 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}