Skip to content

Fix sync methods called in async RAR unpacker paths (Unpack29Async, U…#1306

Merged
adamhathcock merged 9 commits into
releasefrom
adam/fix-sync-methods-in-async-api
Apr 28, 2026
Merged

Fix sync methods called in async RAR unpacker paths (Unpack29Async, U…#1306
adamhathcock merged 9 commits into
releasefrom
adam/fix-sync-methods-in-async-api

Conversation

@adamhathcock
Copy link
Copy Markdown
Owner

Fixes: #1304
Supercedes: #1305

This pull request refactors and improves the asynchronous RAR unpacking logic in the SharpCompress library. The main focus is on converting several previously synchronous methods to asynchronous, ensuring that I/O operations do not block the calling thread. Additionally, there are minor dependency version adjustments in the project lock file.

Asynchronous unpacking improvements:

  • Refactored the Unpack29Async method in Unpack.Async.cs to call new asynchronous versions of ReadTables, ReadEndOfBlock, and ReadVMCode, replacing the previous synchronous calls. This ensures that all table reading and related operations are non-blocking. [1] [2] [3]
  • Introduced new asynchronous methods: ReadTablesAsync, ReadEndOfBlockAsync, and ReadVMCodeAsync in Unpack.Async.cs, implementing the logic of their synchronous counterparts using await for buffer reads and other async operations.
  • Updated Unpack5Async in Unpack50.Async.cs to use the new ReadTablesAsync method instead of the synchronous version. [1] [2]

Dependency version updates:

  • Downgraded the Microsoft.NET.ILLink.Tasks package to version 10.0.0 for net10.0 and to 8.0.22 for net8.0 in packages.lock.json to ensure compatibility or address issues with newer versions. [1] [2]

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes async RAR extraction paths that were still invoking synchronous read/write code (breaking async-only streams), by introducing async equivalents in the RAR unpackers and PPMd glue code, plus adding regression tests to ensure async APIs don’t fall back to sync I/O.

Changes:

  • Refactor RAR v1/v5 async unpacking to call newly added async table/VM/filter and buffer-flush methods instead of sync counterparts.
  • Extend the IRarUnpack + PPMd integration to support async character reads and async PPM initialization/decoding.
  • Add/expand async-only stream regression tests for RAR readers/archives; update ILLink.Tasks versions in the lock file.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/SharpCompress.Test/Rar/RarReaderAsyncTests.cs Adds a theory to validate async RAR reader extraction works with an async-only stream wrapper.
tests/SharpCompress.Test/Rar/RarArchiveTests.cs Adds a sync extraction smoke test over multiple RAR fixtures.
tests/SharpCompress.Test/Rar/RarArchiveAsyncTests.cs Adds an async extraction smoke test over multiple RAR fixtures.
tests/SharpCompress.Test/Mocks/AsyncOnlyStream.cs Refactors AsyncOnlyStream to use a primary constructor.
src/SharpCompress/packages.lock.json Adjusts resolved/requested versions of Microsoft.NET.ILLink.Tasks for net10.0 and net8.0.
src/SharpCompress/IO/AsyncBinaryReader.cs Minor refactor to expression-bodied async methods.
src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack20_async.cs Replaces remaining sync buffer flush + “last tables” logic with async equivalents.
src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.unpack15_async.cs Switches remaining sync buffer flush calls to async.
src/SharpCompress/Compressors/Rar/UnpackV2017/Unpack.cs Replaces Char property with ReadChar()/ReadCharAsync() for PPMd integration.
src/SharpCompress/Compressors/Rar/UnpackV1/Unpack50.Async.cs Converts ReadTables / UnpWriteBuf / filter-add path to async in Unpack5Async.
src/SharpCompress/Compressors/Rar/UnpackV1/Unpack20.Async.cs Switches final table read + buffer flush to async and adds async “last tables” helper.
src/SharpCompress/Compressors/Rar/UnpackV1/Unpack15.Async.cs Switches remaining sync buffer flush calls to async.
src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.cs Replaces Char property with ReadChar() for PPMd integration.
src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.Async.cs Refactors Unpack29Async to fully async table/VM/PPM paths; adds async implementations of key helper methods.
src/SharpCompress/Compressors/Rar/IRarUnpack.cs Updates the interface from Char to ReadChar() + ReadCharAsync(...).
src/SharpCompress/Compressors/PPMd/H/RangeCoder.cs Switches to ReadChar()/ReadCharAsync() and adds async init from IRarUnpack.
src/SharpCompress/Compressors/PPMd/H/ModelPPM.cs Switches sync init to ReadChar() and adds async init using IRarUnpack.
src/SharpCompress/Common/Rar/AsyncMarkingBinaryReader.cs Wraps incomplete async reads as InvalidFormatException for consistency with sync reader behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +8 to +10
public class AsyncOnlyStream(Stream stream) : Stream
{
private readonly Stream _stream;

public AsyncOnlyStream(Stream stream)
{
_stream = stream ?? throw new ArgumentNullException(nameof(stream));
}
private readonly Stream _stream = stream ?? throw new ArgumentNullException(nameof(stream));
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AsyncOnlyStream is intended to enforce async-only usage, but it still allows synchronous operations like Write(...) (and Flush/WriteByte via the base implementation). This undermines tests that wrap output streams with AsyncOnlyStream to detect accidental sync writes. Consider throwing NotSupportedException for synchronous write/flush APIs as well (and optionally overriding WriteByte/Flush/FlushAsync as needed) so the helper reliably catches sync usage.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is covered with #1307

Comment thread src/SharpCompress/Compressors/Rar/UnpackV1/Unpack.Async.cs
Comment thread src/SharpCompress/Common/Rar/AsyncMarkingBinaryReader.cs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants