h2/frame/
util.rs

1use std::fmt;
2
3use super::Error;
4use bytes::Bytes;
5
6/// Strip padding from the given payload.
7///
8/// It is assumed that the frame had the padded flag set. This means that the
9/// first byte is the length of the padding with that many
10/// 0 bytes expected to follow the actual payload.
11///
12/// # Returns
13///
14/// A slice of the given payload where the actual one is found and the length
15/// of the padding.
16///
17/// If the padded payload is invalid (e.g. the length of the padding is equal
18/// to the total length), returns `None`.
19pub fn strip_padding(payload: &mut Bytes) -> Result<u8, Error> {
20    let payload_len = payload.len();
21    if payload_len == 0 {
22        // If this is the case, the frame is invalid as no padding length can be
23        // extracted, even though the frame should be padded.
24        return Err(Error::TooMuchPadding);
25    }
26
27    let pad_len = payload[0] as usize;
28
29    if pad_len >= payload_len {
30        // This is invalid: the padding length MUST be less than the
31        // total frame size.
32        return Err(Error::TooMuchPadding);
33    }
34
35    let _ = payload.split_to(1);
36    let _ = payload.split_off(payload_len - pad_len - 1);
37
38    Ok(pad_len as u8)
39}
40
41pub(super) fn debug_flags<'a, 'f: 'a>(
42    fmt: &'a mut fmt::Formatter<'f>,
43    bits: u8,
44) -> DebugFlags<'a, 'f> {
45    let result = write!(fmt, "({:#x}", bits);
46    DebugFlags {
47        fmt,
48        result,
49        started: false,
50    }
51}
52
53pub(super) struct DebugFlags<'a, 'f: 'a> {
54    fmt: &'a mut fmt::Formatter<'f>,
55    result: fmt::Result,
56    started: bool,
57}
58
59impl<'a, 'f: 'a> DebugFlags<'a, 'f> {
60    pub(super) fn flag_if(&mut self, enabled: bool, name: &str) -> &mut Self {
61        if enabled {
62            self.result = self.result.and_then(|()| {
63                let prefix = if self.started {
64                    " | "
65                } else {
66                    self.started = true;
67                    ": "
68                };
69
70                write!(self.fmt, "{}{}", prefix, name)
71            });
72        }
73        self
74    }
75
76    pub(super) fn finish(&mut self) -> fmt::Result {
77        self.result.and_then(|()| write!(self.fmt, ")"))
78    }
79}