1
0
mirror of https://github.com/chylex/Brotli-Builder.git synced 2025-04-13 00:15:42 +02:00

Implement Brotli literal context mode serialization

This commit is contained in:
chylex 2018-11-21 17:01:08 +01:00
parent 87d65a8b6f
commit 3fe5a82239
2 changed files with 101 additions and 0 deletions
BrotliLib/Brotli/Components/Utils
UnitTests/Brotli

View File

@ -0,0 +1,91 @@
using System;
using BrotliLib.IO;
namespace BrotliLib.Brotli.Components.Utils{
/// <summary>
/// Lists functions for context modeling of literals.
/// https://tools.ietf.org/html/rfc7932#section-7.1
/// </summary>
public enum LiteralContextMode{
LSB6 = 0b00,
MSB6 = 0b01,
UTF8 = 0b10,
Signed = 0b11
}
public static class LiteralContextModes{
public static int DetermineContextID(this LiteralContextMode mode, byte mostRecentByte, byte secondRecentByte){
switch(mode){
case LiteralContextMode.LSB6: return mostRecentByte & 0x3F;
case LiteralContextMode.MSB6: return mostRecentByte >> 2;
case LiteralContextMode.UTF8: return LUT0[mostRecentByte] | LUT1[secondRecentByte];
case LiteralContextMode.Signed: return (LUT2[mostRecentByte] << 3) | LUT2[secondRecentByte];
default: throw new InvalidOperationException("Invalid literal context mode: "+mode);
}
}
public static readonly IBitSerializer<LiteralContextMode, NoContext> Serializer = new BitSerializer<LiteralContextMode, NoContext>(
fromBits: (reader, context) => (LiteralContextMode)reader.NextChunk(2),
toBits: (writer, obj, context) => writer.WriteChunk(2, (int)obj)
);
// Magic
private static readonly byte[] LUT0 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12,
44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12,
12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48,
52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12,
12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56,
60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
};
private static readonly byte[] LUT1 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
};
private static readonly byte[] LUT2 = {
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
};
}
}

View File

@ -5,6 +5,7 @@ open System
open BrotliLib.IO
open BrotliLib.Brotli.Components
open BrotliLib.Brotli.Components.Header
open BrotliLib.Brotli.Components.Utils
module Helper =
@ -101,3 +102,12 @@ module DistanceParameters =
[<InlineData(4, 16)>]
let ``constructing distance parameters with invalid value throws exception`` (pb: byte, db: byte) =
Assert.Throws<ArgumentOutOfRangeException>(fun () -> DistanceParameters(pb, db) |> ignore)
module LiteralContextMode =
let values: obj array seq = Enum.GetValues(typeof<LiteralContextMode>) :?> (LiteralContextMode[]) |> Seq.map(fun value -> [| value |])
[<Theory>]
[<MemberData("values")>]
let ``converting to and from bits yields same object`` (mode: LiteralContextMode) =
Assert.Equal(mode, Helper.convert mode NoContext.Value LiteralContextModes.Serializer)