mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-22 15:04:43 +00:00
add extension methods for checks
This commit is contained in:
@@ -99,7 +99,7 @@ public static partial class ArchiveFactory
|
||||
throw new ArchiveOperationException("No streams");
|
||||
}
|
||||
|
||||
EnsureSeekable(streamsArray);
|
||||
streamsArray.RequireSeekable();
|
||||
|
||||
var firstStream = streamsArray[0];
|
||||
if (streamsArray.Count == 1)
|
||||
@@ -145,11 +145,8 @@ public static partial class ArchiveFactory
|
||||
)
|
||||
where T : IFactory
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
stream.RequireReadable();
|
||||
stream.RequireSeekable();
|
||||
|
||||
var factories = Factory.Factories.OfType<T>();
|
||||
|
||||
|
||||
@@ -13,22 +13,6 @@ namespace SharpCompress.Archives;
|
||||
|
||||
public static partial class ArchiveFactory
|
||||
{
|
||||
internal static void EnsureSeekable(Stream stream)
|
||||
{
|
||||
if (stream is null || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
}
|
||||
|
||||
internal static void EnsureSeekable(IReadOnlyList<Stream> streams)
|
||||
{
|
||||
foreach (var stream in streams)
|
||||
{
|
||||
EnsureSeekable(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
readerOptions ??= ReaderOptions.ForExternalStream;
|
||||
@@ -96,7 +80,7 @@ public static partial class ArchiveFactory
|
||||
throw new ArchiveOperationException("No streams");
|
||||
}
|
||||
|
||||
EnsureSeekable(streamsArray);
|
||||
streamsArray.RequireSeekable();
|
||||
|
||||
var firstStream = streamsArray[0];
|
||||
if (streamsArray.Count == 1)
|
||||
@@ -139,11 +123,8 @@ public static partial class ArchiveFactory
|
||||
public static T FindFactory<T>(Stream stream)
|
||||
where T : IFactory
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
stream.RequireReadable();
|
||||
stream.RequireSeekable();
|
||||
|
||||
var factories = Factory.Factories.OfType<T>();
|
||||
|
||||
@@ -178,12 +159,8 @@ public static partial class ArchiveFactory
|
||||
public static bool IsArchive(Stream stream, out ArchiveType? type)
|
||||
{
|
||||
type = null;
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
stream.RequireReadable();
|
||||
stream.RequireSeekable();
|
||||
|
||||
var startPosition = stream.Position;
|
||||
|
||||
@@ -217,12 +194,8 @@ public static partial class ArchiveFactory
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (!stream.CanRead || !stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream should be readable and seekable");
|
||||
}
|
||||
stream.RequireReadable();
|
||||
stream.RequireSeekable();
|
||||
|
||||
var startPosition = stream.Position;
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public partial class GZipArchive
|
||||
)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
var strms = streams;
|
||||
return new GZipArchive(
|
||||
new SourceStream(
|
||||
@@ -93,12 +93,7 @@ public partial class GZipArchive
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (stream is not { CanSeek: true })
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
stream.RequireSeekable();
|
||||
|
||||
return new GZipArchive(
|
||||
new SourceStream(stream, _ => null, readerOptions ?? ReaderOptions.ForExternalStream)
|
||||
|
||||
@@ -58,12 +58,7 @@ public partial class RarArchive
|
||||
|
||||
public static IRarArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (stream is not { CanSeek: true })
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
stream.RequireSeekable();
|
||||
|
||||
return new RarArchive(
|
||||
new SourceStream(stream, _ => null, readerOptions ?? ReaderOptions.ForExternalStream)
|
||||
@@ -92,7 +87,7 @@ public partial class RarArchive
|
||||
)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
var strms = streams;
|
||||
return new RarArchive(
|
||||
new SourceStream(
|
||||
|
||||
@@ -72,7 +72,7 @@ public partial class SevenZipArchive
|
||||
)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
var strms = streams;
|
||||
return new SevenZipArchive(
|
||||
new SourceStream(
|
||||
@@ -85,12 +85,7 @@ public partial class SevenZipArchive
|
||||
|
||||
public static IArchive OpenArchive(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (stream is not { CanSeek: true })
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
stream.RequireSeekable();
|
||||
|
||||
return new SevenZipArchive(
|
||||
new SourceStream(stream, _ => null, readerOptions ?? ReaderOptions.ForExternalStream)
|
||||
|
||||
@@ -67,7 +67,7 @@ public partial class TarArchive
|
||||
)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
var strms = streams;
|
||||
var sourceStream = new SourceStream(
|
||||
strms[0],
|
||||
@@ -87,12 +87,7 @@ public partial class TarArchive
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (stream is not { CanSeek: true })
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
stream.RequireSeekable();
|
||||
|
||||
return OpenArchive([stream], readerOptions);
|
||||
}
|
||||
@@ -104,10 +99,7 @@ public partial class TarArchive
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
stream.RequireSeekable();
|
||||
var sourceStream = new SourceStream(
|
||||
stream,
|
||||
i => null,
|
||||
@@ -164,7 +156,7 @@ public partial class TarArchive
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
streams.NotNull(nameof(streams));
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
var strms = streams;
|
||||
var sourceStream = new SourceStream(
|
||||
strms[0],
|
||||
|
||||
@@ -68,7 +68,7 @@ public partial class ZipArchive
|
||||
)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
var strms = streams;
|
||||
return new ZipArchive(
|
||||
new SourceStream(
|
||||
@@ -84,12 +84,7 @@ public partial class ZipArchive
|
||||
ReaderOptions? readerOptions = null
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (stream is not { CanSeek: true })
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
stream.RequireSeekable();
|
||||
|
||||
return new ZipArchive(
|
||||
new SourceStream(stream, i => null, readerOptions ?? ReaderOptions.ForExternalStream)
|
||||
@@ -133,7 +128,7 @@ public partial class ZipArchive
|
||||
)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
SharpCompress.Archives.ArchiveFactory.EnsureSeekable(streams);
|
||||
streams.RequireSeekable();
|
||||
return new((IWritableAsyncArchive<ZipWriterOptions>)OpenArchive(streams, readerOptions));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public partial class AceReader
|
||||
/// <returns>An AceReader instance.</returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new SingleVolumeAceReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ public partial class AceReader
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(IEnumerable<Stream> streams, ReaderOptions? options = null)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
return new MultiVolumeAceReader(streams, options ?? ReaderOptions.ForExternalStream);
|
||||
var streamArray = streams.RequireReadable();
|
||||
return new MultiVolumeAceReader(streamArray, options ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
public static ValueTask<IAsyncReader> OpenAsyncReader(
|
||||
@@ -61,8 +61,8 @@ public partial class AceReader
|
||||
ReaderOptions? options = null
|
||||
)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
return new MultiVolumeAceReader(streams, options ?? ReaderOptions.ForExternalStream);
|
||||
var streamArray = streams.RequireReadable();
|
||||
return new MultiVolumeAceReader(streamArray, options ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
public static ValueTask<IAsyncReader> OpenAsyncReader(
|
||||
|
||||
@@ -12,7 +12,7 @@ internal class SingleVolumeAceReader : AceReader
|
||||
internal SingleVolumeAceReader(Stream stream, ReaderOptions options)
|
||||
: base(options)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public partial class ArcReader : AbstractReader<ArcEntry, ArcVolume>
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new ArcReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public abstract partial class ArjReader : AbstractReader<ArjEntry, ArjVolume>
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new SingleVolumeArjReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ public abstract partial class ArjReader : AbstractReader<ArjEntry, ArjVolume>
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(IEnumerable<Stream> streams, ReaderOptions? options = null)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
return new MultiVolumeArjReader(streams, options ?? ReaderOptions.ForExternalStream);
|
||||
var streamArray = streams.RequireReadable();
|
||||
return new MultiVolumeArjReader(streamArray, options ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
protected abstract void ValidateArchive(ArjVolume archive);
|
||||
|
||||
@@ -12,7 +12,7 @@ internal class SingleVolumeArjReader : ArjReader
|
||||
internal SingleVolumeArjReader(Stream stream, ReaderOptions options)
|
||||
: base(options)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public partial class GZipReader
|
||||
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new GZipReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public partial class LzwReader
|
||||
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new LzwReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public abstract partial class RarReader : AbstractReader<RarReaderEntry, RarVolu
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new SingleVolumeRarReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
@@ -83,8 +83,8 @@ public abstract partial class RarReader : AbstractReader<RarReaderEntry, RarVolu
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(IEnumerable<Stream> streams, ReaderOptions? options = null)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
return new MultiVolumeRarReader(streams, options ?? ReaderOptions.ForExternalStream);
|
||||
var streamArray = streams.RequireReadable();
|
||||
return new MultiVolumeRarReader(streamArray, options ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
protected override IEnumerable<RarReaderEntry> GetEntries(Stream stream)
|
||||
|
||||
@@ -56,7 +56,7 @@ public static partial class ReaderFactory
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
options ??= ReaderOptions.ForExternalStream;
|
||||
|
||||
var sharpCompressStream = SharpCompressStream.Create(
|
||||
|
||||
@@ -29,7 +29,7 @@ public static partial class ReaderFactory
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
options ??= ReaderOptions.ForExternalStream;
|
||||
|
||||
var sharpCompressStream = SharpCompressStream.Create(
|
||||
|
||||
@@ -170,7 +170,7 @@ public partial class TarReader
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
readerOptions ??= ReaderOptions.ForExternalStream;
|
||||
var sharpCompressStream = SharpCompressStream.Create(
|
||||
stream,
|
||||
|
||||
@@ -47,7 +47,7 @@ public partial class ZipReader : AbstractReader<ZipEntry, ZipVolume>
|
||||
/// <returns></returns>
|
||||
public static IReader OpenReader(Stream stream, ReaderOptions? readerOptions = null)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new ZipReader(stream, readerOptions ?? ReaderOptions.ForExternalStream);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public partial class ZipReader : AbstractReader<ZipEntry, ZipVolume>
|
||||
IEnumerable<ZipEntry> entries
|
||||
)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
stream.RequireReadable();
|
||||
return new ZipReader(stream, options ?? ReaderOptions.ForExternalStream, entries);
|
||||
}
|
||||
|
||||
|
||||
58
src/SharpCompress/StreamValidationExtensions.cs
Normal file
58
src/SharpCompress/StreamValidationExtensions.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace SharpCompress;
|
||||
|
||||
internal static class StreamValidationExtensions
|
||||
{
|
||||
internal static Stream RequireReadable(this Stream stream)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (!stream.CanRead)
|
||||
{
|
||||
throw new ArgumentException("Stream must be readable", nameof(stream));
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
internal static Stream RequireSeekable(this Stream stream)
|
||||
{
|
||||
stream.NotNull(nameof(stream));
|
||||
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream must be seekable", nameof(stream));
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
internal static IReadOnlyList<Stream> RequireSeekable(this IReadOnlyList<Stream> streams)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
|
||||
foreach (var stream in streams)
|
||||
{
|
||||
stream.RequireSeekable();
|
||||
}
|
||||
|
||||
return streams;
|
||||
}
|
||||
|
||||
internal static IReadOnlyList<Stream> RequireReadable(this IEnumerable<Stream> streams)
|
||||
{
|
||||
streams.NotNull(nameof(streams));
|
||||
|
||||
var streamArray = streams as IReadOnlyList<Stream> ?? streams.ToArray();
|
||||
foreach (var stream in streamArray)
|
||||
{
|
||||
stream.RequireReadable();
|
||||
}
|
||||
|
||||
return streamArray;
|
||||
}
|
||||
}
|
||||
39
tests/SharpCompress.Test/ReaderFactoryTests.cs
Normal file
39
tests/SharpCompress.Test/ReaderFactoryTests.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Readers;
|
||||
using SharpCompress.Readers.Rar;
|
||||
using SharpCompress.Test.Mocks;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test;
|
||||
|
||||
public class ReaderFactoryTests
|
||||
{
|
||||
[Fact]
|
||||
public void OpenReader_Stream_Throws_On_Unreadable_Stream()
|
||||
{
|
||||
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => ReaderFactory.OpenReader(unreadable));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async ValueTask OpenAsyncReader_Stream_Throws_On_Unreadable_Stream()
|
||||
{
|
||||
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
||||
|
||||
await Assert.ThrowsAsync<ArgumentException>(() =>
|
||||
ReaderFactory.OpenAsyncReader(unreadable).AsTask()
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RarReader_StreamCollection_Throws_On_Unreadable_Stream()
|
||||
{
|
||||
using var unreadable = new TestStream(new MemoryStream(), false, true, true);
|
||||
using var readable = new MemoryStream();
|
||||
|
||||
Assert.Throws<ArgumentException>(() => RarReader.OpenReader([unreadable, readable]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user