Skip to main content

net_wire/http2/
data.rs

1use super::error::Http2ParseError;
2use super::frame::Http2Frame;
3use super::layout::{PADDED, padding_length, validate_frame, validate_padding};
4use super::types::Http2FrameType;
5
6/// A validated borrowed HTTP/2 DATA frame.
7#[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    /// Parses the first complete DATA frame, enforcing the caller-provided payload maximum.
26    pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
27        Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
28    }
29
30    /// Validates a raw DATA frame's intrinsic layout.
31    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    /// Returns the validated raw frame.
49    pub const fn frame(&self) -> Http2Frame<'a> {
50        self.frame
51    }
52
53    /// Returns the exact represented frame bytes.
54    pub fn as_bytes(&self) -> &'a [u8] {
55        self.frame.as_bytes()
56    }
57
58    /// Returns the DATA payload excluding pad metadata and trailing padding.
59    pub fn data(&self) -> &'a [u8] {
60        &self.frame.payload()[self.data_start..self.data_end]
61    }
62
63    /// Returns the trailing padding bytes.
64    pub fn padding(&self) -> &'a [u8] {
65        &self.frame.payload()[self.data_end..]
66    }
67
68    /// Returns the encoded padding length when PADDED is set.
69    pub fn pad_length(&self) -> Option<u8> {
70        (self.frame.flags() & PADDED != 0).then(|| self.frame.payload()[0])
71    }
72}