Skip to content

Commit 9876ed1

Browse files
authored
Implement BinaryReader.ReadExactly (#106238)
Fix #101614
1 parent 0a594be commit 9876ed1

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

src/libraries/System.Private.CoreLib/src/System/IO/BinaryReader.cs

+16
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,22 @@ public virtual byte[] ReadBytes(int count)
453453
return result;
454454
}
455455

456+
/// <summary>
457+
/// Reads bytes from the current stream and advances the position within the stream until the <paramref name="buffer" /> is filled.
458+
/// </summary>
459+
/// <remarks>
460+
/// When <paramref name="buffer"/> is empty, this read operation will be completed without waiting for available data in the stream.
461+
/// </remarks>
462+
/// <param name="buffer">A region of memory. When this method returns, the contents of this region are replaced by the bytes read from the current stream.</param>
463+
/// <exception cref="ObjectDisposedException">The stream is closed.</exception>
464+
/// <exception cref="IOException">An I/O error occurred.</exception>
465+
/// <exception cref="EndOfStreamException">The end of the stream is reached before filling the <paramref name="buffer" />.</exception>
466+
public virtual void ReadExactly(Span<byte> buffer)
467+
{
468+
ThrowIfDisposed();
469+
_stream.ReadExactly(buffer);
470+
}
471+
456472
private ReadOnlySpan<byte> InternalRead(Span<byte> buffer)
457473
{
458474
Debug.Assert(buffer.Length != 1, "length of 1 should use ReadByte.");

src/libraries/System.Runtime/ref/System.Runtime.cs

+1
Original file line numberDiff line numberDiff line change
@@ -9913,6 +9913,7 @@ protected virtual void FillBuffer(int numBytes) { }
99139913
public virtual int Read(char[] buffer, int index, int count) { throw null; }
99149914
public virtual int Read(System.Span<byte> buffer) { throw null; }
99159915
public virtual int Read(System.Span<char> buffer) { throw null; }
9916+
public virtual void ReadExactly(System.Span<byte> buffer) { throw null; }
99169917
public int Read7BitEncodedInt() { throw null; }
99179918
public long Read7BitEncodedInt64() { throw null; }
99189919
public virtual bool ReadBoolean() { throw null; }

src/libraries/System.Runtime/tests/System.IO.Tests/BinaryReader/BinaryReaderTests.cs

+31
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public void BinaryReader_EofReachedEarlyTests_ThrowsException()
103103
RunTest(writer => writer.Write("hello world"), reader => reader.ReadString());
104104
RunTest(writer => writer.Write(new string('x', 1024 * 1024)), reader => reader.ReadString());
105105

106+
// test reading into a buffer
107+
byte[] byteBuffer = new byte[10];
108+
109+
RunTest(writer => writer.Write(byteBuffer), reader => reader.ReadExactly(byteBuffer));
110+
106111
void RunTest(Action<BinaryWriter> writeAction, Action<BinaryReader> readAction)
107112
{
108113
UTF8Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
@@ -195,6 +200,7 @@ private void ValidateDisposedExceptions(BinaryReader binaryReader)
195200
Assert.Throws<ObjectDisposedException>(() => binaryReader.Read());
196201
Assert.Throws<ObjectDisposedException>(() => binaryReader.Read(byteBuffer, 0, 1));
197202
Assert.Throws<ObjectDisposedException>(() => binaryReader.Read(charBuffer, 0, 1));
203+
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadExactly(byteBuffer));
198204
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadBoolean());
199205
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadByte());
200206
Assert.Throws<ObjectDisposedException>(() => binaryReader.ReadBytes(1));
@@ -438,6 +444,31 @@ public void Read_CharSpan_ThrowIfDisposed()
438444
}
439445
}
440446

447+
[Theory]
448+
[InlineData(100, 10)]
449+
[InlineData(10, 10)]
450+
[InlineData(10, 0)]
451+
[InlineData(0, 0)]
452+
public void ReadExactly_ByteSpan(int sourceSize, int destinationSize)
453+
{
454+
using (var stream = CreateStream())
455+
{
456+
byte[] source = new byte[sourceSize];
457+
new Random(345).NextBytes(source);
458+
stream.Write(source);
459+
stream.Position = 0;
460+
461+
using (var reader = new BinaryReader(stream))
462+
{
463+
byte[] destination = new byte[destinationSize];
464+
465+
reader.ReadExactly(destination);
466+
467+
Assert.Equal(source[..destinationSize], destination);
468+
}
469+
}
470+
}
471+
441472
private class DerivedBinaryReader : BinaryReader
442473
{
443474
public DerivedBinaryReader(Stream input) : base(input) { }

0 commit comments

Comments
 (0)