1
0
mirror of https://github.com/chylex/Brotli-Builder.git synced 2024-11-25 07:42:56 +01:00
Brotli-Builder/BrotliLib/Brotli/Components/Data/BlockSwitchCommand.cs

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);
};
}
}