0
# Compression Utilities
1
2
HPACK compression utilities for HTTP/2 header compression including N-bit integer encoding/decoding, Huffman coding, and efficient stream processing.
3
4
## Capabilities
5
6
### N-bit Integer Encoding
7
8
HPACK integer encoding with configurable bit prefixes for efficient header compression.
9
10
```java { .api }
11
/**
12
* N-bit integer encoder for HPACK compression
13
*/
14
class NBitIntegerEncoder {
15
/** Calculate octets needed to encode value with prefix */
16
static int octetsNeeded(int prefix, long value);
17
18
/** Encode integer value into buffer with bit prefix */
19
static void encode(ByteBuffer buffer, int prefix, long value);
20
21
/** Encode integer with specific prefix bits */
22
static void encode(ByteBuffer buffer, int prefixBits, int prefix, long value);
23
}
24
```
25
26
### N-bit Integer Decoding
27
28
HPACK integer decoding with state management for streaming processing.
29
30
```java { .api }
31
/**
32
* N-bit integer decoder for HPACK decompression
33
*/
34
class NBitIntegerDecoder {
35
/** Create decoder */
36
NBitIntegerDecoder();
37
38
/** Set bit prefix for next decode operation */
39
void setPrefix(int prefix);
40
41
/** Decode integer from buffer as int */
42
int decodeInt(ByteBuffer buffer);
43
44
/** Decode integer from buffer as long */
45
long decodeLong(ByteBuffer buffer);
46
47
/** Reset decoder state for next value */
48
void reset();
49
50
/** Check if decoder is in reset state */
51
boolean isReset();
52
}
53
```
54
55
### N-bit String Decoding
56
57
HPACK string decoding with Huffman support and streaming capabilities.
58
59
```java { .api }
60
/**
61
* N-bit string decoder for HPACK decompression
62
*/
63
class NBitStringDecoder {
64
/** Create string decoder */
65
NBitStringDecoder();
66
67
/** Create with specific Huffman decoder */
68
NBitStringDecoder(HuffmanDecoder huffmanDecoder);
69
70
/** Set bit prefix for string length */
71
void setPrefix(int prefix);
72
73
/** Decode string from buffer */
74
String decode(ByteBuffer buffer);
75
76
/** Reset decoder state */
77
void reset();
78
79
/** Check if decoder needs more data */
80
boolean isNeedMoreData();
81
}
82
```
83
84
### Huffman Coding
85
86
Huffman encoding and decoding for HPACK string compression.
87
88
```java { .api }
89
/**
90
* Huffman coding utilities for HPACK
91
*/
92
class Huffman {
93
/** Huffman encoder for string compression */
94
static class HuffmanEncoder {
95
/** Calculate octets needed for string */
96
static int octetsNeeded(String s);
97
98
/** Calculate octets needed for byte array */
99
static int octetsNeeded(byte[] b);
100
101
/** Encode string into buffer */
102
static void encode(ByteBuffer buffer, String s);
103
104
/** Encode byte array into buffer */
105
static void encode(ByteBuffer buffer, byte[] b);
106
107
/** Calculate octets needed for lowercase encoding */
108
static int octetsNeededLowerCase(String s);
109
110
/** Encode string as lowercase into buffer */
111
static void encodeLowerCase(ByteBuffer buffer, String s);
112
}
113
114
/** Huffman decoder for string decompression */
115
static class HuffmanDecoder {
116
/** Create decoder */
117
HuffmanDecoder();
118
119
/** Set expected decoded length */
120
void setLength(int length);
121
122
/** Decode buffer content to string */
123
String decode(ByteBuffer buffer);
124
125
/** Reset decoder state */
126
void reset();
127
128
/** Check if decoding is complete */
129
boolean isComplete();
130
}
131
}
132
```
133
134
### GZIP Content Decoding
135
136
GZIP content decompression for HTTP content handling.
137
138
```java { .api }
139
/**
140
* GZIP content decoder with streaming support
141
*/
142
class GZIPContentDecoder implements Destroyable {
143
/** Create GZIP decoder */
144
GZIPContentDecoder();
145
146
/** Create with buffer pool */
147
GZIPContentDecoder(ByteBufferPool byteBufferPool);
148
149
/** Create with buffer pool and buffer size */
150
GZIPContentDecoder(ByteBufferPool byteBufferPool, int bufferSize);
151
152
/** Decode compressed content */
153
Content.Chunk decode(Content.Chunk chunk);
154
155
/** Check if decoder is finished */
156
boolean isFinished();
157
158
/** Reset decoder for new stream */
159
void reset();
160
161
/** Destroy decoder and release resources */
162
void destroy();
163
164
/** Get buffer pool */
165
ByteBufferPool getByteBufferPool();
166
167
/** Get buffer size */
168
int getBufferSize();
169
}
170
```
171
172
### Encoding Exception
173
174
Exception class for compression/decompression errors.
175
176
```java { .api }
177
/**
178
* Exception for compression encoding/decoding errors
179
*/
180
class EncodingException extends Exception {
181
/** Create encoding exception with message */
182
EncodingException(String message);
183
184
/** Create encoding exception with message and cause */
185
EncodingException(String message, Throwable cause);
186
}
187
```
188
189
**Usage Examples:**
190
191
```java
192
import org.eclipse.jetty.http.compression.*;
193
import java.nio.ByteBuffer;
194
195
// N-bit integer encoding for HPACK
196
ByteBuffer buffer = ByteBuffer.allocate(16);
197
198
// Encode integer with 5-bit prefix
199
long value = 1024;
200
int prefixBits = 5;
201
202
int octetsNeeded = NBitIntegerEncoder.octetsNeeded(prefixBits, value);
203
NBitIntegerEncoder.encode(buffer, prefixBits, value);
204
205
buffer.flip(); // Prepare for reading
206
207
// N-bit integer decoding
208
NBitIntegerDecoder intDecoder = new NBitIntegerDecoder();
209
intDecoder.setPrefix(prefixBits);
210
211
long decodedValue = intDecoder.decodeLong(buffer); // 1024
212
intDecoder.reset(); // Reset for next value
213
214
// Huffman string encoding
215
String headerValue = "www.example.com";
216
217
// Calculate space needed
218
int huffmanSize = Huffman.HuffmanEncoder.octetsNeeded(headerValue);
219
ByteBuffer huffmanBuffer = ByteBuffer.allocate(huffmanSize + 10);
220
221
// Encode with Huffman compression
222
Huffman.HuffmanEncoder.encode(huffmanBuffer, headerValue);
223
224
// Encode as lowercase (useful for header names)
225
String headerName = "Content-Type";
226
int lowerSize = Huffman.HuffmanEncoder.octetsNeededLowerCase(headerName);
227
ByteBuffer lowerBuffer = ByteBuffer.allocate(lowerSize + 10);
228
Huffman.HuffmanEncoder.encodeLowerCase(lowerBuffer, headerName);
229
230
huffmanBuffer.flip();
231
232
// Huffman string decoding
233
Huffman.HuffmanDecoder huffmanDecoder = new Huffman.HuffmanDecoder();
234
huffmanDecoder.setLength(headerValue.length()); // Expected decoded length
235
236
String decoded = huffmanDecoder.decode(huffmanBuffer);
237
System.out.println(decoded); // "www.example.com"
238
239
huffmanDecoder.reset(); // Reset for next string
240
241
// N-bit string decoding with Huffman support
242
NBitStringDecoder stringDecoder = new NBitStringDecoder(huffmanDecoder);
243
244
// Prepare string with length prefix and Huffman flag
245
ByteBuffer stringBuffer = ByteBuffer.allocate(64);
246
247
// Encode string length with Huffman flag (bit 7 set)
248
int stringLength = huffmanSize;
249
boolean huffmanEncoded = true;
250
int lengthPrefix = huffmanEncoded ? (0x80 | stringLength) : stringLength;
251
252
stringBuffer.put((byte) lengthPrefix);
253
stringBuffer.put(huffmanBuffer.array(), 0, huffmanSize);
254
stringBuffer.flip();
255
256
// Decode string
257
stringDecoder.setPrefix(7); // 7-bit prefix for string length
258
String decodedString = stringDecoder.decode(stringBuffer);
259
stringDecoder.reset();
260
261
// GZIP content decoding
262
ByteBufferPool bufferPool = new ArrayByteBufferPool();
263
GZIPContentDecoder gzipDecoder = new GZIPContentDecoder(bufferPool, 8192);
264
265
// Simulate compressed content chunks
266
byte[] compressedData = compressWithGzip("Hello, World!");
267
Content.Chunk compressedChunk = Content.Chunk.from(ByteBuffer.wrap(compressedData), false);
268
269
// Decode content
270
Content.Chunk decodedChunk = gzipDecoder.decode(compressedChunk);
271
if (decodedChunk != null) {
272
ByteBuffer decodedBuffer = decodedChunk.getByteBuffer();
273
String decodedText = StandardCharsets.UTF_8.decode(decodedBuffer).toString();
274
System.out.println(decodedText); // "Hello, World!"
275
}
276
277
// Check if decoding is complete
278
boolean finished = gzipDecoder.isFinished();
279
280
// Reset for new stream
281
gzipDecoder.reset();
282
283
// Clean up
284
gzipDecoder.destroy();
285
286
// Complete HPACK header encoding example
287
class HPACKHeaderEncoder {
288
private final ByteBuffer buffer;
289
290
HPACKHeaderEncoder() {
291
this.buffer = ByteBuffer.allocate(4096);
292
}
293
294
void encodeHeader(String name, String value, boolean huffman) {
295
// Encode header name
296
if (huffman) {
297
int nameSize = Huffman.HuffmanEncoder.octetsNeededLowerCase(name);
298
// Set Huffman flag (bit 7) and encode length with 7-bit prefix
299
NBitIntegerEncoder.encode(buffer, 7, 0x80 | nameSize);
300
Huffman.HuffmanEncoder.encodeLowerCase(buffer, name);
301
} else {
302
NBitIntegerEncoder.encode(buffer, 7, name.length());
303
buffer.put(name.toLowerCase().getBytes(StandardCharsets.UTF_8));
304
}
305
306
// Encode header value
307
if (huffman) {
308
int valueSize = Huffman.HuffmanEncoder.octetsNeeded(value);
309
NBitIntegerEncoder.encode(buffer, 7, 0x80 | valueSize);
310
Huffman.HuffmanEncoder.encode(buffer, value);
311
} else {
312
NBitIntegerEncoder.encode(buffer, 7, value.length());
313
buffer.put(value.getBytes(StandardCharsets.UTF_8));
314
}
315
}
316
317
ByteBuffer getBuffer() {
318
buffer.flip();
319
return buffer.asReadOnlyBuffer();
320
}
321
}
322
323
// Use HPACK encoder
324
HPACKHeaderEncoder encoder = new HPACKHeaderEncoder();
325
encoder.encodeHeader("content-type", "application/json", true);
326
encoder.encodeHeader("content-length", "1024", false);
327
328
ByteBuffer encodedHeaders = encoder.getBuffer();
329
330
// Error handling
331
try {
332
// Encoding/decoding operations that might fail
333
Huffman.HuffmanDecoder decoder = new Huffman.HuffmanDecoder();
334
decoder.setLength(100);
335
String result = decoder.decode(corruptedBuffer);
336
} catch (Exception e) {
337
if (e.getCause() instanceof EncodingException) {
338
EncodingException encodingError = (EncodingException) e.getCause();
339
System.err.println("Compression error: " + encodingError.getMessage());
340
}
341
}
342
343
// Helper method for GZIP compression (implementation would use actual GZIP)
344
private byte[] compressWithGzip(String data) {
345
// Implementation would use GZIPOutputStream
346
return data.getBytes(StandardCharsets.UTF_8); // Simplified
347
}
348
```