1 | use std::fmt; |
2 | |
3 | use super::Error; |
4 | use 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`. |
19 | pub fn strip_padding(payload: &mut Bytes) -> Result<u8, Error> { |
20 | let payload_len: usize = 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: usize = 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(at:1); |
36 | let _ = payload.split_off(at:payload_len - pad_len - 1); |
37 | |
38 | Ok(pad_len as u8) |
39 | } |
40 | |
41 | pub(super) fn debug_flags<'a, 'f: 'a>( |
42 | fmt: &'a mut fmt::Formatter<'f>, |
43 | bits: u8, |
44 | ) -> DebugFlags<'a, 'f> { |
45 | let result: Result<(), Error> = write!(fmt, "( {:#x}" , bits); |
46 | DebugFlags { |
47 | fmt, |
48 | result, |
49 | started: false, |
50 | } |
51 | } |
52 | |
53 | pub(super) struct DebugFlags<'a, 'f: 'a> { |
54 | fmt: &'a mut fmt::Formatter<'f>, |
55 | result: fmt::Result, |
56 | started: bool, |
57 | } |
58 | |
59 | impl<'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: &str = 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 | } |
80 | |