mirror of
https://github.com/chylex/Brotli-Builder.git
synced 2024-11-25 07:42:56 +01:00
99 lines
3.4 KiB
C#
99 lines
3.4 KiB
C#
using System;
|
|
using BrotliLib.Brotli.Components.Header;
|
|
using BrotliLib.Brotli.Encode.Build;
|
|
using BrotliLib.Brotli.Utils;
|
|
using BrotliLib.Markers.Serialization;
|
|
using BrotliLib.Serialization;
|
|
|
|
namespace BrotliLib.Brotli.Components.Data{
|
|
public sealed class BlockSwitchCommand{
|
|
private const int FinalCommandLengthPlaceholder = -1;
|
|
|
|
/// <summary>
|
|
/// Next block type.
|
|
/// </summary>
|
|
public byte Type { get; }
|
|
|
|
/// <summary>
|
|
/// Next block length, or an invalid value when <see cref="IsFinalPlaceholder"/> is true.
|
|
/// </summary>
|
|
public int Length { get; }
|
|
|
|
/// <summary>
|
|
/// Returns true if the command was generated by <see cref="BlockSwitchBuilder.AddFinalBlock"/>.
|
|
/// </summary>
|
|
public bool IsFinalPlaceholder => Length == FinalCommandLengthPlaceholder;
|
|
|
|
public BlockSwitchCommand(byte type, int length){
|
|
BlockLengthCode.CheckBounds(length);
|
|
|
|
this.Type = type;
|
|
this.Length = length;
|
|
}
|
|
|
|
internal BlockSwitchCommand(byte type){
|
|
this.Type = type;
|
|
this.Length = FinalCommandLengthPlaceholder;
|
|
}
|
|
|
|
// Object
|
|
|
|
public override bool Equals(object obj){
|
|
return obj is BlockSwitchCommand command &&
|
|
Type == command.Type &&
|
|
Length == command.Length;
|
|
}
|
|
|
|
public override int GetHashCode(){
|
|
return HashCode.Combine(Type, Length);
|
|
}
|
|
|
|
public override string ToString(){
|
|
return "Type = " + Type + ", Length = " + Length;
|
|
}
|
|
|
|
// Context
|
|
|
|
public sealed class Context{
|
|
public BlockTypeInfo Info { get; }
|
|
public BlockTypeTracker Tracker { get; }
|
|
|
|
public Context(BlockTypeInfo info, BlockTypeTracker tracker){
|
|
this.Info = info;
|
|
this.Tracker = tracker;
|
|
}
|
|
}
|
|
|
|
// Serialization
|
|
|
|
public static readonly BitDeserializer<BlockSwitchCommand, Context> Deserialize = MarkedBitDeserializer.Title<BlockSwitchCommand, Context>(
|
|
"Block Switch Command",
|
|
|
|
(reader, context) => {
|
|
var info = context.Info;
|
|
|
|
var typeCode = reader.ReadValue(info.TypeCodeTree!.Root, "BTYPE (code)");
|
|
byte typeValue = reader.MarkValue("BTYPE (value)", () => context.Tracker.NextType(typeCode));
|
|
|
|
var lengthCode = reader.ReadValue(info.LengthCodeTree!.Root, "BLEN (code)");
|
|
int lengthValue = reader.ReadValue(BlockLengthCode.Deserialize, lengthCode, "BLEN (value)");
|
|
|
|
return new BlockSwitchCommand(typeValue, lengthValue);
|
|
}
|
|
);
|
|
|
|
public static readonly BitSerializer<BlockSwitchCommand, Context> Serialize = (writer, obj, context) => {
|
|
var info = context.Info;
|
|
|
|
var typeCodes = context.Tracker.FindCodes(obj.Type);
|
|
writer.WriteBits(info.TypeCodeTree!.FindShortest(typeCodes, (code, available) => available.Contains(code)).Value);
|
|
|
|
int lengthValue = obj.Length;
|
|
var lengthEntry = info.LengthCodeTree!.FindShortest(lengthValue, (code, value) => code.CanEncodeValue(value));
|
|
|
|
writer.WriteBits(lengthEntry.Value);
|
|
BlockLengthCode.Serialize(writer, lengthValue, lengthEntry.Key);
|
|
};
|
|
}
|
|
}
|