private static void Decompress_WithState(ReadOnlySpan <byte> input, Span <byte> output) { BrotliDecoder decoder = default; while (!input.IsEmpty && !output.IsEmpty) { decoder.Decompress(input, output, out int bytesConsumed, out int written); input = input.Slice(bytesConsumed); output = output.Slice(written); } }
public void ReadFully(string testFile) { byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(testFile)); byte[] actualUncompressedBytes = new byte[correctUncompressedBytes.Length + 10000]; ReadOnlySpan <byte> source = new ReadOnlySpan <byte>(compressedBytes); Span <byte> destination = new Span <byte>(actualUncompressedBytes); Assert.True(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress did not complete successfully"); Assert.Equal(correctUncompressedBytes.Length, bytesWritten); Assert.Equal <byte>(correctUncompressedBytes, actualUncompressedBytes.AsSpan(0, correctUncompressedBytes.Length).ToArray()); }
public void WriteFully(string testFile) { byte[] correctUncompressedBytes = File.ReadAllBytes(testFile); byte[] compressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)]; byte[] actualUncompressedBytes = new byte[BrotliEncoder.GetMaxCompressedLength(correctUncompressedBytes.Length)]; Span <byte> destination = new Span <byte>(compressedBytes); Assert.True(BrotliEncoder.TryCompress(correctUncompressedBytes, destination, out int bytesWritten)); Assert.True(BrotliDecoder.TryDecompress(destination, actualUncompressedBytes, out bytesWritten)); Assert.Equal(correctUncompressedBytes.Length, bytesWritten); Assert.Equal <byte>(correctUncompressedBytes, actualUncompressedBytes.AsSpan(0, correctUncompressedBytes.Length).ToArray()); }
public void Decompress_WithEmptySource() { string testFile = UncompressedTestFile(); byte[] sourceBytes = new byte[0]; byte[] destinationBytes = new byte[100000]; ReadOnlySpan <byte> source = new ReadOnlySpan <byte>(sourceBytes); Span <byte> destination = new Span <byte>(destinationBytes); Assert.False(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress completed successfully but should have failed due to too short of a source array"); Assert.Equal(0, bytesWritten); BrotliDecoder decoder; var result = decoder.Decompress(source, destination, out int bytesConsumed, out bytesWritten); Assert.Equal(0, bytesWritten); Assert.Equal(0, bytesConsumed); Assert.Equal(OperationStatus.NeedMoreData, result); }
public void Decompress_WithEmptyDestination() { string testFile = UncompressedTestFile(); byte[] sourceBytes = File.ReadAllBytes(CompressedTestFile(testFile)); byte[] destinationBytes = new byte[0]; ReadOnlySpan <byte> source = new ReadOnlySpan <byte>(sourceBytes); Span <byte> destination = new Span <byte>(destinationBytes); Assert.False(BrotliDecoder.TryDecompress(source, destination, out int bytesWritten), "TryDecompress completed successfully but should have failed due to too short of a destination array"); Assert.Equal(0, bytesWritten); BrotliDecoder decoder = default; var result = decoder.Decompress(source, destination, out int bytesConsumed, out bytesWritten); Assert.Equal(0, bytesWritten); Assert.Equal(0, bytesConsumed); Assert.Equal(OperationStatus.DestinationTooSmall, result); }
public static bool WriteBlockAndPreamble(TrackingPipeWriter writer, NettraceBlock block) { if (block.Type.Name != KnownTypeNames.EventBlockCompressed && block.Type.Name != KnownTypeNames.StackBlockCompressed) { return(false); } var padding = BlockHelpers.GetPadding(writer, block); var prefixLength = padding + sizeof(int); using var decoder = new BrotliDecoder(); var source = ArrayPool <byte> .Shared.Rent((int)block.BlockBody.Length); block.BlockBody.CopyTo(source); var written = 0; Memory <byte> memory; try { var length = prefixLength + (int)block.BlockBody.Length; memory = writer.GetMemory(length); while (!BrotliDecoder.TryDecompress(source.AsSpan(0, (int)block.BlockBody.Length), memory.Slice(prefixLength).Span, out written)) { length = memory.Length * 2; memory = writer.GetMemory(length); } } finally { ArrayPool <byte> .Shared.Return(source); } // Write size BitConverter.TryWriteBytes(memory.Span, written); // clear padding bits memory.Slice(sizeof(int), padding).Span.Clear(); writer.Advance(written + prefixLength); return(true); }
public bool TryDecompress(byte[] source, int sourceOffset, int sourceLength, byte[] destination, int destinationOffset, int destinationLength, out int written) { return(BrotliDecoder.TryDecompress(new ReadOnlySpan <byte>(source, sourceOffset, sourceLength), new Span <byte>(destination, destinationOffset, destinationLength), out written)); }
private static void Decompress_WithoutState(ReadOnlySpan <byte> input, Span <byte> output) { BrotliDecoder.TryDecompress(input, output, out int bytesWritten); }
internal Usmap(IGenericReader fileReader, UsmapOptions options) { var magic = fileReader.Read <ushort>(); if (magic != MAGIC) { throw new FileLoadException("Invalid .usmap magic constant"); } var version = fileReader.Read <EUsmapVersion>(); if (version != EUsmapVersion.LATEST) { throw new FileLoadException($"Invalid .usmap version: {(int)version}"); } var compMethod = fileReader.Read <EUsmapCompressionMethod>(); var compSize = fileReader.Read <uint>(); var decompSize = fileReader.Read <uint>(); if (fileReader.Size - fileReader.Position < compSize) { throw new FileLoadException("There is not enough data in the .usmap file"); } options ??= new UsmapOptions(); IGenericReader reader; switch (compMethod) { case EUsmapCompressionMethod.None: { if (compSize != decompSize) { throw new FileLoadException("No .usmap compression: Compression size must be equal to decompression size"); } reader = fileReader; break; } case EUsmapCompressionMethod.Oodle: { if (options.OodlePath == null) { throw new FileLoadException("Undefined oodle library path"); } if (!File.Exists(options.OodlePath)) { throw new FileLoadException($"Could not find oodle library at \"{options.OodlePath}\""); } var compData = fileReader.ReadBytes((int)compSize); fileReader.Dispose(); var data = new byte[decompSize]; using var decompressor = new OodleCompressor(options.OodlePath); unsafe { var result = decompressor.Decompress(compData, compSize, data, decompSize, OodleLZ_FuzzSafe.No, OodleLZ_CheckCRC.No, OodleLZ_Verbosity.None, 0L, 0L, 0L, 0L, 0L, 0L, OodleLZ_Decode_ThreadPhase.Unthreaded); if (result != decompSize) { throw new FileLoadException($"Invalid oodle .usmap decompress result: {result} / {decompSize}"); } } reader = new GenericBufferReader(data); break; } case EUsmapCompressionMethod.Brotli: { var compData = fileReader.ReadBytes((int)compSize); fileReader.Dispose(); var data = new byte[decompSize]; using var decoder = new BrotliDecoder(); var result = decoder.Decompress(compData, data, out var bytesConsumed, out var bytesWritten); if (result != OperationStatus.Done) { throw new FileLoadException($"Invalid brotli .usmap decompress result: {result} | {bytesWritten} / {decompSize} | {bytesConsumed} / {compSize}"); } reader = new GenericBufferReader(data); break; } default: throw new FileLoadException($"Unknown .usmap compression method: {(int)compMethod}"); } string[] names; { var size = reader.Read <uint>(); names = new string[size]; for (var i = 0; i < size; ++i) { var nameSize = reader.ReadByte(); var name = reader.ReadString(nameSize, Encoding.UTF8); names[i] = name; } } { var size = reader.Read <uint>(); Enums = new UsmapEnum[size]; for (var i = 0; i < size; ++i) { var idx = reader.Read <uint>(); var enumNamesSize = reader.ReadByte(); var enumNames = new string[enumNamesSize]; for (var j = 0; j < enumNamesSize; ++j) { var nameIdx = reader.Read <uint>(); enumNames[j] = names[nameIdx]; } Enums[i] = new UsmapEnum(names[idx], enumNames); } } { var size = reader.Read <uint>(); Schemas = new UsmapSchema[size]; for (var i = 0; i < size; ++i) { var idx = reader.Read <uint>(); var superIdx = reader.Read <uint>(); var propCount = reader.Read <ushort>(); var serializablePropCount = reader.Read <ushort>(); var props = new UsmapProperty[serializablePropCount]; for (var j = 0; j < serializablePropCount; ++j) { var schemaIdx = reader.Read <ushort>(); var arraySize = reader.Read <byte>(); var nameIdx = reader.Read <uint>(); var data = UsmapPropertyData.Deserialize(reader, names); props[j] = new UsmapProperty(names[nameIdx], schemaIdx, arraySize, data); } Schemas[i] = new UsmapSchema(names[idx], superIdx == uint.MaxValue ? null : names[superIdx], propCount, props); } } Names = options.SaveNames ? names : null; reader.Dispose(); }