Class Encoder

java.lang.Object
org.glassfish.grizzly.http2.hpack.Encoder

public class Encoder extends Object
Encodes headers to their binary representation.

Typical lifecycle looks like this:

new Encoder (setMaxCapacity? encode)*

Suppose headers are represented by Map<String, List<String>>. A supplier and a consumer of Buffers in forms of Supplier<ByteBuffer> and Consumer<ByteBuffer> respectively. Then to encode headers, the following approach might be used:

 
     for (Map.Entry<String, List<String>> h : headers.entrySet()) {
         String name = h.getKey();
         for (String value : h.getValue()) {
             encoder.header(name, value);        // Set up header
             boolean encoded;
             do {
                 ByteBuffer b = buffersSupplier.get();
                 encoded = encoder.encode(b);    // Encode the header
                 buffersConsumer.accept(b);
             } while (!encoded);
         }
     }
 
 

Though the specification does not define how an encoder is to be implemented, a default implementation is provided by the method header(CharSequence, CharSequence, boolean).

To provide a custom encoding implementation, Encoder has to be extended. A subclass then can access methods for encoding using specific representations (e.g. literal, indexed, etc.)

An Encoder provides an incremental way of encoding headers. encode(Buffer) takes a buffer a returns a boolean indicating whether, or not, the buffer was sufficiently sized to hold the remaining of the encoded representation.

This way, there's no need to provide a buffer of a specific size, or to resize (and copy) the buffer on demand, when the remaining encoded representation will not fit in the buffer's remaining space. Instead, an array of existing buffers can be used, prepended with a frame that encloses the resulting header block afterwards.

Splitting the encoding operation into header set up and header encoding, separates long lived arguments (name, value, sensitivity, etc.) from the short lived ones (e.g. buffer), simplifying each operation itself.

The default implementation does not use dynamic table. It reports to a coupled Decoder a size update with the value of 0, and never changes it afterwards.