1use super::error::Http2ParseError;
2use super::frame::Http2Frame;
3use super::layout::{PADDED, padding_length, validate_frame, validate_padding};
4use super::types::Http2FrameType;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct Http2Data<'a> {
9 frame: Http2Frame<'a>,
10 data_start: usize,
11 data_end: usize,
12}
13
14impl<'a> Http2Data<'a> {
15 pub(super) fn from_validated(frame: Http2Frame<'a>, padding_length: Option<u8>) -> Self {
16 let data_start = usize::from(padding_length.is_some());
17 let data_end = frame.payload().len() - usize::from(padding_length.unwrap_or(0));
18 Self {
19 frame,
20 data_start,
21 data_end,
22 }
23 }
24
25 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
27 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
28 }
29
30 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
32 validate_frame(frame, Http2FrameType::DATA)?;
33 let payload = frame.payload();
34 let data_start = if frame.flags() & PADDED != 0 {
35 validate_padding(payload)?;
36 1
37 } else {
38 0
39 };
40 let data_end = payload.len() - padding_length(frame);
41 Ok(Self {
42 frame,
43 data_start,
44 data_end,
45 })
46 }
47
48 pub const fn frame(&self) -> Http2Frame<'a> {
50 self.frame
51 }
52
53 pub fn as_bytes(&self) -> &'a [u8] {
55 self.frame.as_bytes()
56 }
57
58 pub fn data(&self) -> &'a [u8] {
60 &self.frame.payload()[self.data_start..self.data_end]
61 }
62
63 pub fn padding(&self) -> &'a [u8] {
65 &self.frame.payload()[self.data_end..]
66 }
67
68 pub fn pad_length(&self) -> Option<u8> {
70 (self.frame.flags() & PADDED != 0).then(|| self.frame.payload()[0])
71 }
72}