mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-25 08:24:58 +00:00
Fix XZStream to support non-seekable streams
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
This commit is contained in:
@@ -5,6 +5,7 @@ using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.IO;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz;
|
||||
|
||||
@@ -12,9 +13,21 @@ namespace SharpCompress.Compressors.Xz;
|
||||
public sealed partial class XZStream : XZReadOnlyStream
|
||||
{
|
||||
public XZStream(Stream baseStream)
|
||||
: base(baseStream)
|
||||
: base(WrapIfNeeded(baseStream))
|
||||
{
|
||||
_baseStream = baseStream;
|
||||
_baseStream = BaseStream;
|
||||
}
|
||||
|
||||
private static Stream WrapIfNeeded(Stream stream)
|
||||
{
|
||||
// XZ format requires position tracking for padding calculations.
|
||||
// For non-seekable streams, wrap with SharpCompressStream which provides
|
||||
// limited backward seeking via a ring buffer.
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
return SharpCompressStream.Create(stream);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -216,9 +216,9 @@
|
||||
"net10.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[10.0.0, )",
|
||||
"resolved": "10.0.0",
|
||||
"contentHash": "kICGrGYEzCNI3wPzfEXcwNHgTvlvVn9yJDhSdRK+oZQy4jvYH529u7O0xf5ocQKzOMjfS07+3z9PKRIjrFMJDA=="
|
||||
"requested": "[10.0.2, )",
|
||||
"resolved": "10.0.2",
|
||||
"contentHash": "sXdDtMf2qcnbygw9OdE535c2lxSxrZP8gO4UhDJ0xiJbl1wIqXS1OTcTDFTIJPOFd6Mhcm8gPEthqWGUxBsTqw=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
@@ -264,9 +264,9 @@
|
||||
"net8.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.22, )",
|
||||
"resolved": "8.0.22",
|
||||
"contentHash": "MhcMithKEiyyNkD2ZfbDZPmcOdi0GheGfg8saEIIEfD/fol3iHmcV8TsZkD4ZYz5gdUuoX4YtlVySUU7Sxl9SQ=="
|
||||
"requested": "[8.0.23, )",
|
||||
"resolved": "8.0.23",
|
||||
"contentHash": "GqHiB1HbbODWPbY/lc5xLQH8siEEhNA0ptpJCC6X6adtAYNEzu5ZlqV3YHA3Gh7fuEwgA8XqVwMtH2KNtuQM1Q=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
|
||||
@@ -34,4 +34,24 @@ public class XzStreamAsyncTests : XzTestsBase
|
||||
var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false);
|
||||
Assert.Equal(OriginalIndexed, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask CanReadNonSeekableStreamAsync()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(Compressed));
|
||||
var xz = new XZStream(nonSeekable);
|
||||
using var sr = new StreamReader(new AsyncOnlyStream(xz));
|
||||
var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false);
|
||||
Assert.Equal(Original, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask CanReadNonSeekableEmptyStreamAsync()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(CompressedEmpty));
|
||||
var xz = new XZStream(nonSeekable);
|
||||
using var sr = new StreamReader(new AsyncOnlyStream(xz));
|
||||
var uncompressed = await sr.ReadToEndAsync().ConfigureAwait(false);
|
||||
Assert.Equal(OriginalEmpty, uncompressed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz;
|
||||
@@ -32,4 +33,24 @@ public class XzStreamTests : XzTestsBase
|
||||
var uncompressed = sr.ReadToEnd();
|
||||
Assert.Equal(OriginalIndexed, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanReadNonSeekableStream()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(Compressed));
|
||||
var xz = new XZStream(nonSeekable);
|
||||
using var sr = new StreamReader(xz);
|
||||
var uncompressed = sr.ReadToEnd();
|
||||
Assert.Equal(Original, uncompressed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanReadNonSeekableEmptyStream()
|
||||
{
|
||||
var nonSeekable = new ForwardOnlyStream(new MemoryStream(CompressedEmpty));
|
||||
var xz = new XZStream(nonSeekable);
|
||||
using var sr = new StreamReader(xz);
|
||||
var uncompressed = sr.ReadToEnd();
|
||||
Assert.Equal(OriginalEmpty, uncompressed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user