From 885971b1bffe71292634bd39cea870a055610136 Mon Sep 17 00:00:00 2001 From: Jan Pluskal Date: Thu, 30 Jan 2020 10:17:36 +0100 Subject: [PATCH] Introduce GetSizeAsync, IsEofAsync. Fix KaitaiAsyncStream Size delegation to _readerContext. --- .../KaitaiAsyncStreamBaseTests.cs | 18 +- .../Interface/IKaitaiAsyncStream.cs | 329 +++++++++--------- .../Interface/IReaderContext.cs | 4 +- .../KaitaiAsyncStream.cs | 8 +- .../ReaderContext/PipeReaderContext.cs | 4 +- .../ReaderContext/StreamReaderContext.cs | 4 +- 6 files changed, 197 insertions(+), 170 deletions(-) diff --git a/Kaitai.Struct.Runtime.Async.Tests/KaitaiAsyncStreamBaseTests.cs b/Kaitai.Struct.Runtime.Async.Tests/KaitaiAsyncStreamBaseTests.cs index 1d61599..0acf91a 100644 --- a/Kaitai.Struct.Runtime.Async.Tests/KaitaiAsyncStreamBaseTests.cs +++ b/Kaitai.Struct.Runtime.Async.Tests/KaitaiAsyncStreamBaseTests.cs @@ -1,4 +1,5 @@ using System.IO; +using System.IO.Pipelines; using System.Threading.Tasks; using Kaitai.Async; using Xunit; @@ -6,14 +7,14 @@ namespace Kaitai.Struct.Runtime.Async.Tests { public class StreamKaitaiAsyncStreamBaseTests : KaitaiAsyncStreamBaseTests - { + { protected override KaitaiAsyncStream Create(byte[] data) => new KaitaiAsyncStream(data); } public class PipeReaderKaitaiAsyncStreamBaseTests : KaitaiAsyncStreamBaseTests - { + { protected override KaitaiAsyncStream Create(byte[] data) => - new KaitaiAsyncStream(System.IO.Pipelines.PipeReader.Create(new MemoryStream(data))); + new KaitaiAsyncStream(PipeReader.Create(new MemoryStream(data))); } public abstract class KaitaiAsyncStreamBaseTests @@ -34,8 +35,8 @@ public abstract class KaitaiAsyncStreamBaseTests public async Task Eof_Test(bool shouldBeEof, int streamSize, int readBitsAmount) { var kaitaiStreamSUT = Create(new byte[streamSize]); - await kaitaiStreamSUT.ReadBitsIntAsync(readBitsAmount); + long positionBeforeIsEof = kaitaiStreamSUT.Pos; if (shouldBeEof) { @@ -45,6 +46,8 @@ public async Task Eof_Test(bool shouldBeEof, int streamSize, int readBitsAmount) { Assert.False(kaitaiStreamSUT.IsEof); } + + Assert.Equal(positionBeforeIsEof, kaitaiStreamSUT.Pos); } [Theory] @@ -74,11 +77,18 @@ public async Task Pos_BySeek_Test(int expectedPos, int position) [Theory] [InlineData(0)] [InlineData(1)] + [InlineData(100)] + [InlineData(1_000)] + [InlineData(10_000)] + [InlineData(100_000)] + [InlineData(1_000_000)] public void Size_Test(int streamSize) { var kaitaiStreamSUT = Create(new byte[streamSize]); + long positionBeforeIsEof = kaitaiStreamSUT.Pos; Assert.Equal(streamSize, kaitaiStreamSUT.Size); + Assert.Equal(positionBeforeIsEof, kaitaiStreamSUT.Pos); } [Fact] diff --git a/Kaitai.Struct.Runtime.Async/Interface/IKaitaiAsyncStream.cs b/Kaitai.Struct.Runtime.Async/Interface/IKaitaiAsyncStream.cs index 9898416..4df5abb 100644 --- a/Kaitai.Struct.Runtime.Async/Interface/IKaitaiAsyncStream.cs +++ b/Kaitai.Struct.Runtime.Async/Interface/IKaitaiAsyncStream.cs @@ -2,161 +2,174 @@ namespace Kaitai.Async { - public interface IKaitaiAsyncStream : IKaitaiStreamBase - { - /// - /// Seek to a specific position from the beginning of the stream - /// - /// The position to seek to - Task SeekAsync(long position); - - /// - /// Read a signed byte from the stream - /// - /// - Task ReadS1Async(); - - /// - /// Read a signed short from the stream (big endian) - /// - /// - Task ReadS2beAsync(); - - /// - /// Read a signed int from the stream (big endian) - /// - /// - Task ReadS4beAsync(); - - /// - /// Read a signed long from the stream (big endian) - /// - /// - Task ReadS8beAsync(); - - /// - /// Read a signed short from the stream (little endian) - /// - /// - Task ReadS2leAsync(); - - /// - /// Read a signed int from the stream (little endian) - /// - /// - Task ReadS4leAsync(); - - /// - /// Read a signed long from the stream (little endian) - /// - /// - Task ReadS8leAsync(); - - /// - /// Read an unsigned byte from the stream - /// - /// - Task ReadU1Async(); - - /// - /// Read an unsigned short from the stream (big endian) - /// - /// - Task ReadU2beAsync(); - - /// - /// Read an unsigned int from the stream (big endian) - /// - /// - Task ReadU4beAsync(); - - /// - /// Read an unsigned long from the stream (big endian) - /// - /// - Task ReadU8beAsync(); - - /// - /// Read an unsigned short from the stream (little endian) - /// - /// - Task ReadU2leAsync(); - - /// - /// Read an unsigned int from the stream (little endian) - /// - /// - Task ReadU4leAsync(); - - /// - /// Read an unsigned long from the stream (little endian) - /// - /// - Task ReadU8leAsync(); - - /// - /// Read a single-precision floating point value from the stream (big endian) - /// - /// - Task ReadF4beAsync(); - - /// - /// Read a double-precision floating point value from the stream (big endian) - /// - /// - Task ReadF8beAsync(); - - /// - /// Read a single-precision floating point value from the stream (little endian) - /// - /// - Task ReadF4leAsync(); - - /// - /// Read a double-precision floating point value from the stream (little endian) - /// - /// - Task ReadF8leAsync(); - - Task ReadBitsIntAsync(int n); - - Task ReadBitsIntLeAsync(int n); - - /// - /// Read a fixed number of bytes from the stream - /// - /// The number of bytes to read - /// - Task ReadBytesAsync(long count); - - /// - /// Read a fixed number of bytes from the stream - /// - /// The number of bytes to read - /// - Task ReadBytesAsync(ulong count); - - /// - /// Read all the remaining bytes from the stream until the end is reached - /// - /// - Task ReadBytesFullAsync(); - - /// - /// Read a terminated string from the stream - /// - /// The string terminator value - /// True to include the terminator in the returned string - /// True to consume the terminator byte before returning - /// True to throw an error when the EOS was reached before the terminator - /// - Task ReadBytesTermAsync(byte terminator, bool includeTerminator, bool consumeTerminator, bool eosError); - - /// - /// Read a specific set of bytes and assert that they are the same as an expected result - /// - /// The expected result - /// - Task EnsureFixedContentsAsync(byte[] expected); - } -} + public interface IKaitaiAsyncStream : IKaitaiStreamBase + { + /// + /// Check if the stream position is at the end of the stream + /// + ValueTask IsEofAsync(); + + /// + /// Get the total length of the stream (ie. file size) + /// + ValueTask GetSizeAsync(); + + /// + /// Seek to a specific position from the beginning of the stream + /// + /// The position to seek to + Task SeekAsync(long position); + + /// + /// Read a signed byte from the stream + /// + /// + Task ReadS1Async(); + + /// + /// Read a signed short from the stream (big endian) + /// + /// + Task ReadS2beAsync(); + + /// + /// Read a signed int from the stream (big endian) + /// + /// + Task ReadS4beAsync(); + + /// + /// Read a signed long from the stream (big endian) + /// + /// + Task ReadS8beAsync(); + + /// + /// Read a signed short from the stream (little endian) + /// + /// + Task ReadS2leAsync(); + + /// + /// Read a signed int from the stream (little endian) + /// + /// + Task ReadS4leAsync(); + + /// + /// Read a signed long from the stream (little endian) + /// + /// + Task ReadS8leAsync(); + + /// + /// Read an unsigned byte from the stream + /// + /// + Task ReadU1Async(); + + /// + /// Read an unsigned short from the stream (big endian) + /// + /// + Task ReadU2beAsync(); + + /// + /// Read an unsigned int from the stream (big endian) + /// + /// + Task ReadU4beAsync(); + + /// + /// Read an unsigned long from the stream (big endian) + /// + /// + Task ReadU8beAsync(); + + /// + /// Read an unsigned short from the stream (little endian) + /// + /// + Task ReadU2leAsync(); + + /// + /// Read an unsigned int from the stream (little endian) + /// + /// + Task ReadU4leAsync(); + + /// + /// Read an unsigned long from the stream (little endian) + /// + /// + Task ReadU8leAsync(); + + /// + /// Read a single-precision floating point value from the stream (big endian) + /// + /// + Task ReadF4beAsync(); + + /// + /// Read a double-precision floating point value from the stream (big endian) + /// + /// + Task ReadF8beAsync(); + + /// + /// Read a single-precision floating point value from the stream (little endian) + /// + /// + Task ReadF4leAsync(); + + /// + /// Read a double-precision floating point value from the stream (little endian) + /// + /// + Task ReadF8leAsync(); + + Task ReadBitsIntAsync(int n); + + Task ReadBitsIntLeAsync(int n); + + /// + /// Read a fixed number of bytes from the stream + /// + /// The number of bytes to read + /// + Task ReadBytesAsync(long count); + + /// + /// Read a fixed number of bytes from the stream + /// + /// The number of bytes to read + /// + Task ReadBytesAsync(ulong count); + + /// + /// Read all the remaining bytes from the stream until the end is reached + /// + /// + Task ReadBytesFullAsync(); + + /// + /// Read a terminated string from the stream + /// + /// The string terminator value + /// True to include the terminator in the returned string + /// True to consume the terminator byte before returning + /// True to throw an error when the EOS was reached before the terminator + /// + Task ReadBytesTermAsync(byte terminator, + bool includeTerminator, + bool consumeTerminator, + bool eosError); + + /// + /// Read a specific set of bytes and assert that they are the same as an expected result + /// + /// The expected result + /// + Task EnsureFixedContentsAsync(byte[] expected); + } +} \ No newline at end of file diff --git a/Kaitai.Struct.Runtime.Async/Interface/IReaderContext.cs b/Kaitai.Struct.Runtime.Async/Interface/IReaderContext.cs index 1f954d6..4eab4fb 100644 --- a/Kaitai.Struct.Runtime.Async/Interface/IReaderContext.cs +++ b/Kaitai.Struct.Runtime.Async/Interface/IReaderContext.cs @@ -5,8 +5,8 @@ namespace Kaitai.Async public interface IReaderContext { long Position { get; } - ValueTask GetSize(); - ValueTask IsEof(); + ValueTask GetSizeAsync(); + ValueTask IsEofAsync(); ValueTask SeekAsync(long position); ValueTask ReadByteAsync(); ValueTask ReadBytesAsync(long count); diff --git a/Kaitai.Struct.Runtime.Async/KaitaiAsyncStream.cs b/Kaitai.Struct.Runtime.Async/KaitaiAsyncStream.cs index 804a11d..d6e6f5b 100644 --- a/Kaitai.Struct.Runtime.Async/KaitaiAsyncStream.cs +++ b/Kaitai.Struct.Runtime.Async/KaitaiAsyncStream.cs @@ -51,13 +51,17 @@ public KaitaiAsyncStream(byte[] bytes) : this(new MemoryStream(bytes)) #region Stream positioning public override bool IsEof => - _readerContext.IsEof().GetAwaiter().GetResult() && _bitsLeft == 0; //TODO should be async method + _readerContext.IsEofAsync().GetAwaiter().GetResult() && _bitsLeft == 0; + + public ValueTask IsEofAsync() => _readerContext.IsEofAsync(); + + public ValueTask GetSizeAsync() => _readerContext.GetSizeAsync(); public virtual async Task SeekAsync(long position) => await _readerContext.SeekAsync(position); public override long Pos => _readerContext.Position; - public override long Size => ReadBytesFullAsync().GetAwaiter().GetResult().Length; //TODO should be async method + public override long Size => _readerContext.GetSizeAsync().GetAwaiter().GetResult(); #endregion diff --git a/Kaitai.Struct.Runtime.Async/ReaderContext/PipeReaderContext.cs b/Kaitai.Struct.Runtime.Async/ReaderContext/PipeReaderContext.cs index 86c2e1e..e6077ee 100644 --- a/Kaitai.Struct.Runtime.Async/ReaderContext/PipeReaderContext.cs +++ b/Kaitai.Struct.Runtime.Async/ReaderContext/PipeReaderContext.cs @@ -20,14 +20,14 @@ public PipeReaderContext(PipeReader pipeReader) public long Position { get; private set; } - public async ValueTask GetSize() + public async ValueTask GetSizeAsync() { await FillReadResultBufferToTheEnd(); return _readResult.Buffer.Length; } - public async ValueTask IsEof() + public async ValueTask IsEofAsync() { await EnsureReadResultIsNotDefault(); diff --git a/Kaitai.Struct.Runtime.Async/ReaderContext/StreamReaderContext.cs b/Kaitai.Struct.Runtime.Async/ReaderContext/StreamReaderContext.cs index 2a0cd05..60465b2 100644 --- a/Kaitai.Struct.Runtime.Async/ReaderContext/StreamReaderContext.cs +++ b/Kaitai.Struct.Runtime.Async/ReaderContext/StreamReaderContext.cs @@ -17,9 +17,9 @@ public StreamReaderContext(Stream stream) protected AsyncBinaryReader AsyncBinaryReader { get; } public long Position => _baseStream.Position; - public ValueTask GetSize() => new ValueTask(_baseStream.Length); + public ValueTask GetSizeAsync() => new ValueTask(_baseStream.Length); - public ValueTask IsEof() => + public ValueTask IsEofAsync() => new ValueTask(_baseStream.Position >= _baseStream.Length); public ValueTask SeekAsync(long position)