diff --git a/src/SharpCompress/Archives/ArchiveFactory.Async.cs b/src/SharpCompress/Archives/ArchiveFactory.Async.cs
index a96bbefa..6c45cb1f 100644
--- a/src/SharpCompress/Archives/ArchiveFactory.Async.cs
+++ b/src/SharpCompress/Archives/ArchiveFactory.Async.cs
@@ -1,11 +1,9 @@
-using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
-using SharpCompress.Factories;
using SharpCompress.Readers;
namespace SharpCompress.Archives;
@@ -109,118 +107,4 @@ public static partial class ArchiveFactory
.OpenAsyncArchive(streamsArray, options, cancellationToken)
.ConfigureAwait(false);
}
-
- ///
- /// Returns information about the archive at the given file path asynchronously,
- /// or if the file is not a recognized archive.
- ///
- /// Path to the archive file.
- /// Cancellation token.
- public static async ValueTask GetArchiveInformationAsync(
- string filePath,
- CancellationToken cancellationToken = default
- )
- {
- filePath.NotNullOrEmpty(nameof(filePath));
- using Stream stream = File.OpenRead(filePath);
- return await GetArchiveInformationAsync(stream, cancellationToken).ConfigureAwait(false);
- }
-
- ///
- /// Returns information about the archive in the given stream asynchronously,
- /// or if the stream is not a recognized archive.
- ///
- /// A readable and seekable stream positioned at the start of the archive.
- /// Cancellation token.
- public static async ValueTask GetArchiveInformationAsync(
- Stream stream,
- CancellationToken cancellationToken = default
- )
- {
- stream.RequireReadable();
- stream.RequireSeekable();
-
- var factory = await TryFindFactoryAsync(stream, cancellationToken).ConfigureAwait(false);
- return factory is null
- ? null
- : new ArchiveInformation(factory.KnownArchiveType, factory is IArchiveFactory);
- }
-
- internal static ValueTask FindFactoryAsync(
- string filePath,
- CancellationToken cancellationToken = default
- )
- where T : IFactory
- {
- filePath.NotNullOrEmpty(nameof(filePath));
- return FindFactoryAsync(new FileInfo(filePath), cancellationToken);
- }
-
- internal static async ValueTask FindFactoryAsync(
- FileInfo finfo,
- CancellationToken cancellationToken = default
- )
- where T : IFactory
- {
- finfo.NotNull(nameof(finfo));
- using Stream stream = finfo.OpenRead();
- return await FindFactoryAsync(stream, cancellationToken).ConfigureAwait(false);
- }
-
- internal static async ValueTask FindFactoryAsync(
- Stream stream,
- CancellationToken cancellationToken = default
- )
- where T : IFactory
- {
- stream.RequireReadable();
- stream.RequireSeekable();
-
- // Use the shared async detection loop over all factories. If the matched factory
- // implements T we return it; otherwise (or if nothing matched) we fall through
- // to the same "unsupported format" exception that the original code produced,
- // listing the T-typed factories as the hint for the caller.
- var factory = await TryFindFactoryAsync(stream, cancellationToken).ConfigureAwait(false);
- if (factory is T typedFactory)
- {
- return typedFactory;
- }
-
- var extensions = string.Join(", ", Factory.Factories.OfType().Select(item => item.Name));
-
- throw new ArchiveOperationException(
- $"Cannot determine compressed stream type. Supported Archive Formats: {extensions}"
- );
- }
-
- ///
- /// Async counterpart of .
- /// Iterates all registered factories and returns the first one whose
- /// recognises the stream, or .
- /// Stream position is restored to its value at entry on both success and failure.
- ///
- private static async ValueTask TryFindFactoryAsync(
- Stream stream,
- CancellationToken cancellationToken
- )
- {
- var startPosition = stream.Position;
-
- foreach (var factory in Factory.Factories)
- {
- stream.Seek(startPosition, SeekOrigin.Begin);
- if (
- await factory
- .IsArchiveAsync(stream, cancellationToken: cancellationToken)
- .ConfigureAwait(false)
- )
- {
- stream.Seek(startPosition, SeekOrigin.Begin);
- return factory;
- }
- }
-
- stream.Seek(startPosition, SeekOrigin.Begin);
- return null;
- }
}
diff --git a/src/SharpCompress/Archives/ArchiveFactory.Detection.cs b/src/SharpCompress/Archives/ArchiveFactory.Detection.cs
new file mode 100644
index 00000000..ae04e09f
--- /dev/null
+++ b/src/SharpCompress/Archives/ArchiveFactory.Detection.cs
@@ -0,0 +1,187 @@
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using SharpCompress.Common;
+using SharpCompress.Factories;
+using SharpCompress.Readers;
+
+namespace SharpCompress.Archives;
+
+public static partial class ArchiveFactory
+{
+ ///
+ /// Returns information about the archive at the given file path asynchronously,
+ /// or if the file is not a recognized archive.
+ ///
+ /// Path to the archive file.
+ /// Cancellation token.
+ public static async ValueTask GetArchiveInformationAsync(
+ string filePath,
+ CancellationToken cancellationToken = default
+ )
+ {
+ filePath.NotNullOrEmpty(nameof(filePath));
+ using Stream stream = File.OpenRead(filePath);
+ return await GetArchiveInformationAsync(stream, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Returns information about the archive in the given stream asynchronously,
+ /// or if the stream is not a recognized archive.
+ ///
+ /// A readable and seekable stream positioned at the start of the archive.
+ /// Cancellation token.
+ public static async ValueTask GetArchiveInformationAsync(
+ Stream stream,
+ CancellationToken cancellationToken = default
+ )
+ {
+ stream.RequireReadable();
+ stream.RequireSeekable();
+
+ var factory = await TryFindFactoryAsync(stream, cancellationToken).ConfigureAwait(false);
+ return factory is null
+ ? null
+ : new ArchiveInformation(factory.KnownArchiveType, factory is IArchiveFactory);
+ }
+
+ internal static ValueTask FindFactoryAsync(
+ string filePath,
+ CancellationToken cancellationToken = default
+ )
+ where T : IFactory
+ {
+ filePath.NotNullOrEmpty(nameof(filePath));
+ return FindFactoryAsync(new FileInfo(filePath), cancellationToken);
+ }
+
+ internal static async ValueTask FindFactoryAsync(
+ FileInfo fileInfo,
+ CancellationToken cancellationToken = default
+ )
+ where T : IFactory
+ {
+ fileInfo.NotNull(nameof(fileInfo));
+ using Stream stream = fileInfo.OpenRead();
+ return await FindFactoryAsync(stream, cancellationToken).ConfigureAwait(false);
+ }
+
+ internal static async ValueTask FindFactoryAsync(
+ Stream stream,
+ CancellationToken cancellationToken = default
+ )
+ where T : IFactory
+ {
+ stream.RequireReadable();
+ stream.RequireSeekable();
+
+ // Use the shared async detection loop over all factories. If the matched factory
+ // implements T we return it; otherwise (or if nothing matched) we fall through
+ // to the same "unsupported format" exception that the original code produced,
+ // listing the T-typed factories as the hint for the caller.
+ var factory = await TryFindFactoryAsync(stream, cancellationToken).ConfigureAwait(false);
+ if (factory is T typedFactory)
+ {
+ return typedFactory;
+ }
+
+ var extensions = string.Join(", ", Factory.Factories.OfType().Select(item => item.Name));
+
+ throw new ArchiveOperationException(
+ $"Cannot determine compressed stream type. Supported Archive Formats: {extensions}"
+ );
+ }
+
+ ///
+ /// Async counterpart of .
+ /// Iterates all registered factories and returns the first one whose
+ /// recognises the stream, or .
+ /// Stream position is restored to its value at entry on both success and failure.
+ ///
+ private static async ValueTask TryFindFactoryAsync(
+ Stream stream,
+ CancellationToken cancellationToken
+ )
+ {
+ var startPosition = stream.Position;
+
+ foreach (var factory in Factory.Factories)
+ {
+ stream.Seek(startPosition, SeekOrigin.Begin);
+ if (
+ await factory
+ .IsArchiveAsync(stream, cancellationToken: cancellationToken)
+ .ConfigureAwait(false)
+ )
+ {
+ stream.Seek(startPosition, SeekOrigin.Begin);
+ return factory;
+ }
+ }
+
+ stream.Seek(startPosition, SeekOrigin.Begin);
+ return null;
+ }
+
+ ///
+ /// Returns information about the archive at the given file path,
+ /// or if the file is not a recognized archive.
+ ///
+ /// Path to the archive file.
+ public static ArchiveInformation? GetArchiveInformation(string filePath)
+ {
+ filePath.NotNullOrEmpty(nameof(filePath));
+ using Stream stream = File.OpenRead(filePath);
+ return GetArchiveInformation(stream);
+ }
+
+ ///
+ /// Returns information about the archive in the given stream,
+ /// or if the stream is not a recognized archive.
+ ///
+ /// A readable and seekable stream positioned at the start of the archive.
+ public static ArchiveInformation? GetArchiveInformation(Stream stream)
+ {
+ stream.RequireReadable();
+ stream.RequireSeekable();
+
+ var factory = TryFindFactory(stream);
+ return factory is null
+ ? null
+ : new ArchiveInformation(factory.KnownArchiveType, factory is IArchiveFactory);
+ }
+
+ ///
+ /// Iterates all registered factories and returns the first one whose
+ /// recognises the stream, or .
+ /// Stream position is restored to its value at entry on both success and failure.
+ ///
+ ///
+ /// This is the shared, seekable-stream detection core used by
+ /// , ,
+ /// and .
+ ///
+ /// uses a separate code path
+ /// based on rewindable buffering, which supports
+ /// non-seekable streams and is therefore not unified with this helper.
+ ///
+ ///
+ private static IFactory? TryFindFactory(Stream stream)
+ {
+ var startPosition = stream.Position;
+
+ foreach (var factory in Factory.Factories)
+ {
+ stream.Seek(startPosition, SeekOrigin.Begin);
+ if (factory.IsArchive(stream))
+ {
+ stream.Seek(startPosition, SeekOrigin.Begin);
+ return factory;
+ }
+ }
+
+ stream.Seek(startPosition, SeekOrigin.Begin);
+ return null;
+ }
+}
diff --git a/src/SharpCompress/Archives/ArchiveFactory.cs b/src/SharpCompress/Archives/ArchiveFactory.cs
index 0f236a0e..d6f08cc6 100644
--- a/src/SharpCompress/Archives/ArchiveFactory.cs
+++ b/src/SharpCompress/Archives/ArchiveFactory.cs
@@ -157,67 +157,6 @@ public static partial class ArchiveFactory
return factory is not null;
}
- ///
- /// Returns information about the archive at the given file path,
- /// or if the file is not a recognized archive.
- ///
- /// Path to the archive file.
- public static ArchiveInformation? GetArchiveInformation(string filePath)
- {
- filePath.NotNullOrEmpty(nameof(filePath));
- using Stream stream = File.OpenRead(filePath);
- return GetArchiveInformation(stream);
- }
-
- ///
- /// Returns information about the archive in the given stream,
- /// or if the stream is not a recognized archive.
- ///
- /// A readable and seekable stream positioned at the start of the archive.
- public static ArchiveInformation? GetArchiveInformation(Stream stream)
- {
- stream.RequireReadable();
- stream.RequireSeekable();
-
- var factory = TryFindFactory(stream);
- return factory is null
- ? null
- : new ArchiveInformation(factory.KnownArchiveType, factory is IArchiveFactory);
- }
-
- ///
- /// Iterates all registered factories and returns the first one whose
- /// recognises the stream, or .
- /// Stream position is restored to its value at entry on both success and failure.
- ///
- ///
- /// This is the shared, seekable-stream detection core used by
- /// , ,
- /// and .
- ///
- /// uses a separate code path
- /// based on rewindable buffering, which supports
- /// non-seekable streams and is therefore not unified with this helper.
- ///
- ///
- private static IFactory? TryFindFactory(Stream stream)
- {
- var startPosition = stream.Position;
-
- foreach (var factory in Factory.Factories)
- {
- stream.Seek(startPosition, SeekOrigin.Begin);
- if (factory.IsArchive(stream))
- {
- stream.Seek(startPosition, SeekOrigin.Begin);
- return factory;
- }
- }
-
- stream.Seek(startPosition, SeekOrigin.Begin);
- return null;
- }
-
public static async ValueTask<(bool IsArchive, ArchiveType? Type)> IsArchiveAsync(
string filePath,
CancellationToken cancellationToken = default