diff --git a/src/SharpCompress/Compressors/LZMA/ICoder.cs b/src/SharpCompress/Compressors/LZMA/ICoder.cs index 569568f5..71265d70 100644 --- a/src/SharpCompress/Compressors/LZMA/ICoder.cs +++ b/src/SharpCompress/Compressors/LZMA/ICoder.cs @@ -150,7 +150,7 @@ internal enum CoderPropId internal interface ISetCoderProperties { - void SetCoderProperties(CoderPropId[] propIDs, object[] properties); + void SetCoderProperties(ReadOnlySpan propIDs, ReadOnlySpan properties); } internal interface IWriteCoderProperties diff --git a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs index a802bc86..1dfb43b1 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaEncoder.cs @@ -1725,9 +1725,9 @@ internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties return -1; } - public void SetCoderProperties(CoderPropId[] propIDs, object[] properties) + public void SetCoderProperties(ReadOnlySpan propIDs, ReadOnlySpan properties) { - for (uint i = 0; i < properties.Length; i++) + for (int i = 0; i < properties.Length; i++) { var prop = properties[i]; switch (propIDs[i]) diff --git a/src/SharpCompress/Compressors/LZMA/LzmaEncoderProperties.cs b/src/SharpCompress/Compressors/LZMA/LzmaEncoderProperties.cs index 17c43ed6..9a34e219 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaEncoderProperties.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaEncoderProperties.cs @@ -1,9 +1,16 @@ +using System; + namespace SharpCompress.Compressors.LZMA; public class LzmaEncoderProperties { - internal CoderPropId[] _propIDs; - internal object[] _properties; + public static LzmaEncoderProperties Default { get; } = new(); + + internal ReadOnlySpan PropIDs => _propIDs; + private readonly CoderPropId[] _propIDs; + + internal ReadOnlySpan Properties => _properties; + private readonly object[] _properties; public LzmaEncoderProperties() : this(false) { } diff --git a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs index 01fddf17..701b8e64 100644 --- a/src/SharpCompress/Compressors/LZMA/LzmaStream.cs +++ b/src/SharpCompress/Compressors/LZMA/LzmaStream.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System; using System.Buffers.Binary; @@ -111,7 +111,7 @@ public class LzmaStream : Stream } _encoder = new Encoder(); - _encoder.SetCoderProperties(properties._propIDs, properties._properties); + _encoder.SetCoderProperties(properties.PropIDs, properties.Properties); var prop = new byte[5]; _encoder.WriteCoderProperties(prop); Properties = prop; diff --git a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs index ad97cdd4..8c252186 100644 --- a/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs +++ b/tests/SharpCompress.Test/Streams/LzmaStreamTests.cs @@ -1,4 +1,6 @@ using System; +using System.Buffers; +using System.Buffers.Binary; using System.IO; using SharpCompress.Compressors.LZMA; using Xunit; @@ -177,6 +179,9 @@ public class LzmaStreamTests 0x90 }; + /// + /// The decoded data for . + /// private static byte[] lzmaResultData { get; } = new byte[] { @@ -528,4 +533,54 @@ public class LzmaStreamTests Assert.Equal(output.ToArray(), lzmaResultData); } + + [Fact] + public void TestLzmaStreamEncodingWritesData() + { + using MemoryStream inputStream = new MemoryStream(lzmaResultData); + using MemoryStream outputStream = new(); + using LzmaStream lzmaStream = new LzmaStream(LzmaEncoderProperties.Default, false, outputStream); + inputStream.CopyTo(lzmaStream); + lzmaStream.Close(); + Assert.NotEqual(0, outputStream.Length); + } + + [Fact] + public void TestLzmaEncodingAccuracy() + { + var input = new MemoryStream(lzmaResultData); + var compressed = new MemoryStream(); + LzmaStream lzmaEncodingStream = new LzmaStream(LzmaEncoderProperties.Default, false, compressed); + input.CopyTo(lzmaEncodingStream); + lzmaEncodingStream.Close(); + compressed.Position = 0; + + var output = new MemoryStream(); + DecompressLzmaStream(lzmaEncodingStream.Properties, compressed, compressed.Length, output, lzmaResultData.LongLength); + + Assert.Equal(output.ToArray(), lzmaResultData); + } + + private static void DecompressLzmaStream(byte[] properties, Stream compressedStream, long compressedSize, Stream decompressedStream, long decompressedSize) + { + LzmaStream lzmaStream = new LzmaStream(properties, compressedStream, compressedSize, -1, null, false); + + byte[] buffer = ArrayPool.Shared.Rent(1024); + long totalRead = 0; + while (totalRead < decompressedSize) + { + int toRead = (int)Math.Min(buffer.Length, decompressedSize - totalRead); + int read = lzmaStream.Read(buffer, 0, toRead); + if (read > 0) + { + decompressedStream.Write(buffer, 0, read); + totalRead += read; + } + else + { + break; + } + } + ArrayPool.Shared.Return(buffer); + } }