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:
parent
87d65a8b6f
commit
3fe5a82239
91
BrotliLib/Brotli/Components/Utils/LiteralContextMode.cs
Normal file
91
BrotliLib/Brotli/Components/Utils/LiteralContextMode.cs
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user