net_wire/http2/hpack/
huffman.rs1use core::fmt;
4
5use crate::rfc7541_huffman;
6
7pub struct HpackHuffmanEncoder<'input, 'output> {
9 decoded: &'input [u8],
10 destination: &'output mut [u8],
11}
12
13impl<'input, 'output> HpackHuffmanEncoder<'input, 'output> {
14 pub fn new(decoded: &'input [u8], destination: &'output mut [u8]) -> Self {
16 Self {
17 decoded,
18 destination,
19 }
20 }
21
22 pub fn required_encoded_len(decoded: &[u8]) -> Result<usize, HpackHuffmanEncodeError> {
24 rfc7541_huffman::encoded_len(decoded).map_err(map_encode_error)
25 }
26
27 pub fn encode(self) -> Result<&'output [u8], HpackHuffmanEncodeError> {
29 let required = Self::required_encoded_len(self.decoded)?;
30 if self.destination.len() < required {
31 return Err(HpackHuffmanEncodeError::DestinationTooShort {
32 required,
33 available: self.destination.len(),
34 });
35 }
36 let destination = &mut self.destination[..required];
37 Self::encode_prevalidated(self.decoded, destination);
38 Ok(destination)
39 }
40
41 pub(super) fn encode_prevalidated(decoded: &[u8], destination: &mut [u8]) {
43 rfc7541_huffman::encode_prevalidated(decoded, destination);
44 }
45}
46
47#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub enum HpackHuffmanEncodeError {
50 EncodedBitLengthOverflow,
52 EncodedByteLengthOverflow,
54 DestinationTooShort {
56 required: usize,
58 available: usize,
60 },
61}
62
63impl fmt::Display for HpackHuffmanEncodeError {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 match self {
66 Self::EncodedBitLengthOverflow => {
67 f.write_str("HPACK Huffman encoded bit length overflows usize")
68 }
69 Self::EncodedByteLengthOverflow => {
70 f.write_str("HPACK Huffman encoded byte length overflows usize")
71 }
72 Self::DestinationTooShort {
73 required,
74 available,
75 } => write!(
76 f,
77 "HPACK Huffman destination is too short: need {required} bytes, have {available}"
78 ),
79 }
80 }
81}
82
83pub struct HpackHuffmanDecoder<'input, 'output> {
85 encoded: &'input [u8],
86 destination: &'output mut [u8],
87}
88
89impl<'input, 'output> HpackHuffmanDecoder<'input, 'output> {
90 pub fn new(encoded: &'input [u8], destination: &'output mut [u8]) -> Self {
92 Self {
93 encoded,
94 destination,
95 }
96 }
97
98 pub fn required_decoded_len(encoded: &[u8]) -> Result<usize, HpackHuffmanDecodeError> {
100 rfc7541_huffman::decoded_len(encoded).map_err(map_decode_error)
101 }
102
103 pub fn decode(self) -> Result<&'output [u8], HpackHuffmanDecodeError> {
105 let required = Self::required_decoded_len(self.encoded)?;
106 if self.destination.len() < required {
107 return Err(HpackHuffmanDecodeError::OutputTooShort {
108 required,
109 available: self.destination.len(),
110 });
111 }
112 rfc7541_huffman::decode_prevalidated(self.encoded, &mut self.destination[..required]);
113 Ok(&self.destination[..required])
114 }
115}
116
117#[derive(Clone, Copy, Debug, Eq, PartialEq)]
119pub enum HpackHuffmanDecodeError {
120 EosSymbol,
122 InvalidHuffmanCode,
124 InvalidPadding,
126 DecodedLengthOverflow,
128 OutputTooShort {
130 required: usize,
132 available: usize,
134 },
135}
136
137impl fmt::Display for HpackHuffmanDecodeError {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 match self {
140 Self::EosSymbol => f.write_str("HPACK Huffman data contains EOS"),
141 Self::InvalidHuffmanCode => f.write_str("HPACK Huffman data contains an invalid code"),
142 Self::InvalidPadding => {
143 f.write_str("HPACK Huffman data has invalid EOS-prefix padding")
144 }
145 Self::DecodedLengthOverflow => {
146 f.write_str("HPACK Huffman decoded length overflows usize")
147 }
148 Self::OutputTooShort {
149 required,
150 available,
151 } => write!(
152 f,
153 "HPACK Huffman output buffer is too short: need {required} bytes, have {available}"
154 ),
155 }
156 }
157}
158
159fn map_encode_error(error: rfc7541_huffman::EncodeError) -> HpackHuffmanEncodeError {
160 match error {
161 rfc7541_huffman::EncodeError::BitLengthOverflow => {
162 HpackHuffmanEncodeError::EncodedBitLengthOverflow
163 }
164 rfc7541_huffman::EncodeError::ByteLengthOverflow => {
165 HpackHuffmanEncodeError::EncodedByteLengthOverflow
166 }
167 }
168}
169
170fn map_decode_error(error: rfc7541_huffman::DecodeError) -> HpackHuffmanDecodeError {
171 match error {
172 rfc7541_huffman::DecodeError::EosSymbol => HpackHuffmanDecodeError::EosSymbol,
173 rfc7541_huffman::DecodeError::InvalidHuffmanCode => {
174 HpackHuffmanDecodeError::InvalidHuffmanCode
175 }
176 rfc7541_huffman::DecodeError::InvalidPadding => HpackHuffmanDecodeError::InvalidPadding,
177 rfc7541_huffman::DecodeError::DecodedLengthOverflow => {
178 HpackHuffmanDecodeError::DecodedLengthOverflow
179 }
180 }
181}