Issue #9554 - un-duplicate implementation for HuffmanDecoder

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2023-04-05 16:04:04 +10:00
parent f6688b0208
commit 7fb5b422fe
3 changed files with 13 additions and 70 deletions

View File

@ -21,68 +21,11 @@ public class HuffmanDecoder
{
public static String decode(ByteBuffer buffer, int length) throws EncodingException
{
Utf8StringBuilder utf8 = new Utf8StringBuilder(length * 2);
int node = 0;
int current = 0;
int bits = 0;
for (int i = 0; i < length; i++)
{
int b = buffer.get() & 0xFF;
current = (current << 8) | b;
bits += 8;
while (bits >= 8)
{
int c = (current >>> (bits - 8)) & 0xFF;
node = tree[node * 256 + c];
if (rowbits[node] != 0)
{
if (rowsym[node] == EOS)
throw new EncodingException("EOS in content");
// terminal node
utf8.append((byte)(0xFF & rowsym[node]));
bits -= rowbits[node];
node = 0;
}
else
{
// non-terminal node
bits -= 8;
}
}
}
while (bits > 0)
{
int c = (current << (8 - bits)) & 0xFF;
int lastNode = node;
node = tree[node * 256 + c];
if (rowbits[node] == 0 || rowbits[node] > bits)
{
int requiredPadding = 0;
for (int i = 0; i < bits; i++)
{
requiredPadding = (requiredPadding << 1) | 1;
}
if ((c >> (8 - bits)) != requiredPadding)
throw new EncodingException("Incorrect padding");
node = lastNode;
break;
}
utf8.append((byte)(0xFF & rowsym[node]));
bits -= rowbits[node];
node = 0;
}
if (node != 0)
throw new EncodingException("Bad termination");
return utf8.toCompleteString();
HuffmanDecoder huffmanDecoder = new HuffmanDecoder();
huffmanDecoder.setLength(length);
String decoded = huffmanDecoder.decode(buffer);
huffmanDecoder.reset();
return decoded;
}
static final char EOS = HuffmanEncoder.EOS;

View File

@ -17,9 +17,9 @@ import java.nio.ByteBuffer;
public class NBitIntegerParser
{
public static int decode(ByteBuffer buffer, int n)
public static int decode(ByteBuffer buffer, int prefix)
{
if (n == 8)
if (prefix == 8)
{
int nbits = 0xFF;
@ -40,7 +40,7 @@ public class NBitIntegerParser
return i;
}
int nbits = 0xFF >>> (8 - n);
int nbits = 0xFF >>> (8 - prefix);
int i = buffer.get(buffer.position() - 1) & nbits;

View File

@ -466,7 +466,7 @@ public class HpackDecoderTest
String encoded = "82868441" + "84" + "49509FFF";
ByteBuffer buffer = ByteBuffer.wrap(StringUtil.fromHexString(encoded));
CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Bad termination"));
assertThat(ex.getMessage(), Matchers.containsString("bad_termination"));
}
/* 5.2.2: Sends a Huffman-encoded string literal representation padded by zero */
@ -479,7 +479,7 @@ public class HpackDecoderTest
ByteBuffer buffer = ByteBuffer.wrap(StringUtil.fromHexString(encoded));
CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Incorrect padding"));
assertThat(ex.getMessage(), Matchers.containsString("incorrect_padding"));
}
/* 5.2.3: Sends a Huffman-encoded string literal representation containing the EOS symbol */
@ -492,7 +492,7 @@ public class HpackDecoderTest
ByteBuffer buffer = ByteBuffer.wrap(StringUtil.fromHexString(encoded));
CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("EOS in content"));
assertThat(ex.getMessage(), Matchers.containsString("eos_in_content"));
}
@Test
@ -504,7 +504,7 @@ public class HpackDecoderTest
ByteBuffer buffer = ByteBuffer.wrap(StringUtil.fromHexString(encoded));
CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Bad termination"));
assertThat(ex.getMessage(), Matchers.containsString("bad_termination"));
}
@Test
@ -516,7 +516,7 @@ public class HpackDecoderTest
ByteBuffer buffer = ByteBuffer.wrap(StringUtil.fromHexString(encoded));
CompressionException ex = assertThrows(CompressionException.class, () -> decoder.decode(buffer));
assertThat(ex.getMessage(), Matchers.containsString("Bad termination"));
assertThat(ex.getMessage(), Matchers.containsString("bad_termination"));
}
@Test