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 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 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 pub fn stream_id(&self) -> StreamId {
40 self.stream_id
41 }
42
43 pub fn is_end_stream(&self) -> bool {
51 self.flags.is_end_stream()
52 }
53
54 pub fn set_end_stream(&mut self) {
56 self.flags.set_end_stream();
57 }
58
59 pub fn is_padded(&self) -> bool {
61 self.flags.is_padded()
62 }
63
64 pub fn set_padded(&mut self) {
66 self.flags.set_padded();
67 }
68
69 pub fn payload(&self) -> &Bytes {
74 &self.data
75 }
76
77 pub fn payload_mut(&mut self) -> &mut Bytes {
82 &mut self.data
83 }
84
85 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 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 pub(crate) fn encode(&self, dst: &mut BytesMut) {
118 self.head().encode(self.data.len(), dst);
120 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 f.finish()
141 }
142}
143
144impl 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}