Class Encoder
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.
-
Constructor Summary
ConstructorsConstructorDescriptionEncoder(int maxCapacity) Constructs anEncoderwith the specified maximum capacity of the header table. -
Method Summary
Modifier and TypeMethodDescriptionprotected intcalculateCapacity(int maxCapacity) protected final voidfinal booleanEncodes the set up header into the given buffer.protected final org.glassfish.grizzly.http2.hpack.HeaderTableprotected final intvoidheader(CharSequence name, CharSequence value) Sets up the given header(name, value).voidheader(CharSequence name, CharSequence value, boolean sensitive) Sets up the given header(name, value)with possibly sensitive value.protected final voidindexed(int index) protected final voidliteral(int index, CharSequence value, boolean useHuffman) protected final voidliteral(CharSequence name, boolean nameHuffman, CharSequence value, boolean valueHuffman) protected final voidliteralNeverIndexed(int index, CharSequence value, boolean valueHuffman) protected final voidliteralNeverIndexed(CharSequence name, boolean nameHuffman, CharSequence value, boolean valueHuffman) protected final voidliteralWithIndexing(int index, CharSequence value, boolean valueHuffman) protected final voidliteralWithIndexing(CharSequence name, boolean nameHuffman, CharSequence value, boolean valueHuffman) voidsetMaxCapacity(int capacity) Sets a maximum capacity of the header table.protected final voidsizeUpdate(int capacity)
-
Constructor Details
-
Encoder
public Encoder(int maxCapacity) Constructs anEncoderwith the specified maximum capacity of the header table.The value has to be agreed between decoder and encoder out-of-band, e.g. by a protocol that uses HPACK (see 4.2. Maximum Table Size).
- Parameters:
maxCapacity- a non-negative integer- Throws:
IllegalArgumentException- if maxCapacity is negative
-
-
Method Details
-
header
Sets up the given header(name, value).Fixates
nameandvaluefor the duration of encoding.- Parameters:
name- the namevalue- the value- Throws:
NullPointerException- if any of the arguments arenullIllegalStateException- if the encoder hasn't fully encoded the previous header, or hasn't yet started to encode it- See Also:
-
header
public void header(CharSequence name, CharSequence value, boolean sensitive) throws IllegalStateException Sets up the given header(name, value)with possibly sensitive value.Fixates
nameandvaluefor the duration of encoding.- Parameters:
name- the namevalue- the valuesensitive- whether or not the value is sensitive- Throws:
NullPointerException- if any of the arguments arenullIllegalStateException- if the encoder hasn't fully encoded the previous header, or hasn't yet started to encode it- See Also:
-
setMaxCapacity
public void setMaxCapacity(int capacity) Sets a maximum capacity of the header table.The value has to be agreed between decoder and encoder out-of-band, e.g. by a protocol that uses HPACK (see 4.2. Maximum Table Size).
May be called any number of times after or before a complete header has been encoded.
If the encoder decides to change the actual capacity, an update will be encoded before a new encoding operation starts.
- Parameters:
capacity- a non-negative integer- Throws:
IllegalArgumentException- if capacity is negativeIllegalStateException- if the encoder hasn't fully encoded the previous header, or hasn't yet started to encode it
-
calculateCapacity
protected int calculateCapacity(int maxCapacity) -
encode
Encodes the set up header into the given buffer.The encoder writes as much as possible of the header's binary representation into the given buffer, starting at the buffer's position, and increments its position to reflect the bytes written. The buffer's mark and limit will not be modified.
Once the method has returned
true, the current header is deemed encoded. A new header may be set up.- Parameters:
headerBlock- the buffer to encode the header into, may be empty- Returns:
trueif the current header has been fully encoded,falseotherwise- Throws:
NullPointerException- if the buffer isnullReadOnlyBufferException- if this buffer is read-onlyIllegalStateException- if there is no set up header
-
indexed
- Throws:
IndexOutOfBoundsException
-
literal
protected final void literal(int index, CharSequence value, boolean useHuffman) throws IndexOutOfBoundsException - Throws:
IndexOutOfBoundsException
-
literal
protected final void literal(CharSequence name, boolean nameHuffman, CharSequence value, boolean valueHuffman) -
literalNeverIndexed
protected final void literalNeverIndexed(int index, CharSequence value, boolean valueHuffman) throws IndexOutOfBoundsException - Throws:
IndexOutOfBoundsException
-
literalNeverIndexed
protected final void literalNeverIndexed(CharSequence name, boolean nameHuffman, CharSequence value, boolean valueHuffman) -
literalWithIndexing
protected final void literalWithIndexing(int index, CharSequence value, boolean valueHuffman) throws IndexOutOfBoundsException - Throws:
IndexOutOfBoundsException
-
literalWithIndexing
protected final void literalWithIndexing(CharSequence name, boolean nameHuffman, CharSequence value, boolean valueHuffman) -
sizeUpdate
- Throws:
IllegalArgumentException
-
getMaxCapacity
protected final int getMaxCapacity() -
getHeaderTable
-
checkEncoding
protected final void checkEncoding()
-