diff --git a/src/Bedrock.Framework/Protocols/ConsumableArrayBufferWriter.cs b/src/Bedrock.Framework/Protocols/ConsumableArrayBufferWriter.cs index 3d4292cd..44c4226b 100644 --- a/src/Bedrock.Framework/Protocols/ConsumableArrayBufferWriter.cs +++ b/src/Bedrock.Framework/Protocols/ConsumableArrayBufferWriter.cs @@ -4,31 +4,27 @@ namespace Bedrock.Framework.Protocols { - /// - /// This should be replaced with the framework version if https://github.com/dotnet/runtime/issues/1248 is implemented - /// - /// - internal class ConsumableArrayBufferWriter : IBufferWriter + internal class ConsumableArrayBufferWriter : IBufferWriter, IDisposable { - private T[] _buffer; + private byte[] _buffer; private int _index; private int _consumedCount; private const int DefaultInitialBufferSize = 256; /// - /// Creates an instance of an , in which data can be written to, + /// Creates an instance of an , in which data can be written to, /// with the default initial capacity. /// public ConsumableArrayBufferWriter() { - _buffer = Array.Empty(); + _buffer = Array.Empty(); _index = 0; _consumedCount = 0; } /// - /// Creates an instance of an , in which data can be written to, + /// Creates an instance of an , in which data can be written to, /// with an initial capacity specified. /// /// The minimum capacity with which to initialize the underlying buffer. @@ -40,20 +36,20 @@ public ConsumableArrayBufferWriter(int initialCapacity) if (initialCapacity <= 0) throw new ArgumentException(nameof(initialCapacity)); - _buffer = new T[initialCapacity]; + _buffer = ArrayPool.Shared.Rent(initialCapacity); _index = 0; _consumedCount = 0; } /// - /// Returns the unconsumed data written to the underlying buffer so far, as a . + /// Returns the unconsumed data written to the underlying buffer so far, as a . /// - public ReadOnlyMemory WrittenMemory => _buffer.AsMemory(_consumedCount.._index); + public ReadOnlyMemory WrittenMemory => _buffer.AsMemory(_consumedCount.._index); /// - /// Returns the unconsumed data written to the underlying buffer so far, as a . + /// Returns the unconsumed data written to the underlying buffer so far, as a . /// - public ReadOnlySpan WrittenSpan => _buffer.AsSpan(_consumedCount.._index); + public ReadOnlySpan WrittenSpan => _buffer.AsSpan(_consumedCount.._index); /// /// Returns the amount of unconsumed data written to the underlying buffer so far. @@ -74,7 +70,7 @@ public ConsumableArrayBufferWriter(int initialCapacity) /// Clears the data written to the underlying buffer. /// /// - /// You must clear the before trying to re-use it. + /// You must clear the before trying to re-use it. /// public void Clear() { @@ -85,7 +81,7 @@ public void Clear() } /// - /// Notifies that amount of data was written to the output / + /// Notifies that amount of data was written to the output / /// /// /// Thrown when is negative. @@ -108,7 +104,7 @@ public void Advance(int count) } /// - /// Notifies that amount of data was consumed from the output / + /// Notifies that amount of data was consumed from the output / /// /// /// Thrown when is negative. @@ -132,6 +128,12 @@ public void Consume(int count) { _index = 0; _consumedCount = 0; + if (Capacity >= DefaultInitialBufferSize * 2) + { + // No point holding on to a large buffer + ArrayPool.Shared.Return(_buffer); + _buffer = Array.Empty(); + } } else { @@ -140,14 +142,14 @@ public void Consume(int count) } /// - /// Returns a to write to that is at least the requested length (specified by ). + /// Returns a to write to that is at least the requested length (specified by ). /// If no is provided (or it's equal to 0), some non-empty buffer is returned. /// /// /// Thrown when is negative. /// /// - /// This will never return an empty . + /// This will never return an empty . /// /// /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. @@ -155,7 +157,7 @@ public void Consume(int count) /// /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. /// - public Memory GetMemory(int sizeHint = 0) + public Memory GetMemory(int sizeHint = 0) { CheckAndResizeBuffer(sizeHint); Debug.Assert(_buffer.Length > _index); @@ -163,14 +165,14 @@ public Memory GetMemory(int sizeHint = 0) } /// - /// Returns a to write to that is at least the requested length (specified by ). + /// Returns a to write to that is at least the requested length (specified by ). /// If no is provided (or it's equal to 0), some non-empty buffer is returned. /// /// /// Thrown when is negative. /// /// - /// This will never return an empty . + /// This will never return an empty . /// /// /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. @@ -178,7 +180,7 @@ public Memory GetMemory(int sizeHint = 0) /// /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. /// - public Span GetSpan(int sizeHint = 0) + public Span GetSpan(int sizeHint = 0) { CheckAndResizeBuffer(sizeHint); Debug.Assert(_buffer.Length > _index); @@ -216,8 +218,9 @@ private void CheckAndResizeBuffer(int sizeHint) } var newSize = checked(_buffer.Length + growBy); - var destinationArray = new T[newSize]; + var destinationArray = ArrayPool.Shared.Rent(newSize); Array.Copy(_buffer, _consumedCount, destinationArray, 0, countUnconsumed); + ReturnBuffer(); _buffer = destinationArray; } _index = countUnconsumed; @@ -226,5 +229,16 @@ private void CheckAndResizeBuffer(int sizeHint) Debug.Assert(FreeCapacity > 0 && FreeCapacity >= sizeHint); } + + public void Dispose() + { + ReturnBuffer(); + _buffer = null; // This will cause a NRE if we use after dispose rather than writing data into a random array + } + + private void ReturnBuffer() + { + ArrayPool.Shared.Return(_buffer); + } } } diff --git a/src/Bedrock.Framework/Protocols/MessagePipeReader.cs b/src/Bedrock.Framework/Protocols/MessagePipeReader.cs index 8c68433b..89d71e19 100644 --- a/src/Bedrock.Framework/Protocols/MessagePipeReader.cs +++ b/src/Bedrock.Framework/Protocols/MessagePipeReader.cs @@ -18,7 +18,7 @@ public class MessagePipeReader : PipeReader private bool _isThisCompleted; private bool _isCanceled; private bool _isCompleted; - private ConsumableArrayBufferWriter _backlog = new ConsumableArrayBufferWriter(); + private readonly ConsumableArrayBufferWriter _backlog = new ConsumableArrayBufferWriter(); private bool _allExamined; private bool _advanced = true; public MessagePipeReader(PipeReader reader, IMessageReader> messageReader) @@ -80,7 +80,7 @@ public override void Complete(Exception exception = null) _reader.AdvanceTo(_consumed, _examined); } _isThisCompleted = true; - _backlog = null; + _backlog.Dispose(); } public override async ValueTask ReadAsync(CancellationToken cancellationToken = default) diff --git a/tests/Bedrock.Framework.Tests/ConsumableArrayBufferWriterTests.cs b/tests/Bedrock.Framework.Tests/ConsumableArrayBufferWriterTests.cs index c82135ea..2dbcf97b 100644 --- a/tests/Bedrock.Framework.Tests/ConsumableArrayBufferWriterTests.cs +++ b/tests/Bedrock.Framework.Tests/ConsumableArrayBufferWriterTests.cs @@ -2,18 +2,16 @@ using System; using System.Buffers; using System.Collections.Generic; -using System.Diagnostics; -using System.Text; using Xunit; namespace Bedrock.Framework.Tests { - public abstract class ConsumableArrayBufferWriterTests where T : IEquatable + public class ConsumableArrayBufferWriterTests { [Fact] public void ThrowsIfConsumeIsLessThanZero() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 1); Assert.Throws(() => output.Consume(-1)); } @@ -21,7 +19,7 @@ public void ThrowsIfConsumeIsLessThanZero() [Fact] public void ThrowsIfTotalConsumedIsGreaterThanWritten() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); Assert.Throws(() => output.Consume(1)); WriteData(output, 2); output.Consume(1); @@ -34,29 +32,53 @@ public void ThrowsIfTotalConsumedIsGreaterThanWritten() [Fact] public void ThrowsIfConsumePlusConsumedWouldOverflow() { - var output = new ConsumableArrayBufferWriter(256); + var output = new ConsumableArrayBufferWriter(256); WriteData(output, 100); output.Consume(50); Assert.Throws(() => output.Consume(int.MaxValue)); } [Fact] - public void IfConsumedEqualsWrittenFreeCapacityIsReset() + public void IfConsumedEqualsWritten_AndCapacityIsSmall_FreeCapacityIsReset() { - var output = new ConsumableArrayBufferWriter(256); - Assert.Equal(256, output.FreeCapacity); + ConsumableArrayBufferWriter output; + do + { + output = new ConsumableArrayBufferWriter(256); + } + while (output.Capacity >= 512); + + var capacity = output.Capacity; + Assert.InRange(capacity, 256, 512); + Assert.Equal(capacity, output.FreeCapacity); + WriteData(output, 128); + Assert.Equal(capacity - 128, output.FreeCapacity); + output.Consume(64); + Assert.Equal(capacity - 128, output.FreeCapacity); + output.Consume(64); + Assert.Equal(capacity, output.FreeCapacity); + } + + [Fact] + public void IfConsumedEqualsWritten_AndCapacityIsLarge_BackingArrayIsReturned() + { + var output = new ConsumableArrayBufferWriter(512); + var capacity = output.Capacity; + Assert.InRange(capacity, 512, int.MaxValue); + Assert.Equal(capacity, output.FreeCapacity); WriteData(output, 128); - Assert.Equal(128, output.FreeCapacity); + Assert.Equal(capacity - 128, output.FreeCapacity); output.Consume(64); - Assert.Equal(128, output.FreeCapacity); + Assert.Equal(capacity - 128, output.FreeCapacity); output.Consume(64); - Assert.Equal(256, output.FreeCapacity); + Assert.Equal(0, output.Capacity); + Assert.Equal(0, output.FreeCapacity); } [Fact] public void ConsumeReducesUnconsumedWrittenCount() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 2); Assert.Equal(2, output.UnconsumedWrittenCount); output.Consume(1); @@ -66,7 +88,7 @@ public void ConsumeReducesUnconsumedWrittenCount() [Fact] public void ConsumeIsNotIncludedInWrittenSpanOrMemory() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 2); var oldSpan = output.WrittenSpan; var oldMemory = output.WrittenMemory; @@ -84,43 +106,39 @@ public void ConsumeIsNotIncludedInWrittenSpanOrMemory() [Fact] public void CapacityDoesNotIncreaseIfThereIsPlentyOfConsumedSpace() { - var output = new ConsumableArrayBufferWriter(256); - WriteData(output, 256); - output.Consume(156); + var output = new ConsumableArrayBufferWriter(256); + var capacity = output.Capacity; + WriteData(output, capacity); + output.Consume(capacity - 100); var data = output.WrittenSpan.ToArray(); output.GetMemory(16); - Assert.Equal(256, output.Capacity); + Assert.Equal(capacity, output.Capacity); Assert.Equal(data, output.WrittenSpan.ToArray()); - Assert.Equal(156, output.FreeCapacity); + Assert.Equal(capacity - 100, output.FreeCapacity); Assert.Equal(100, output.UnconsumedWrittenCount); } [Fact] - public void CapacityDoesIncreaseIfThereIsNotEnoughConsumedSpace() + public void CapacityDoesIncreaseIfThereIsOnlyMinimalConsumedSpace() { - var output = new ConsumableArrayBufferWriter(256); - WriteData(output, 256); - output.Consume(16); + var output = new ConsumableArrayBufferWriter(256); + var capacity = output.Capacity; + WriteData(output, capacity); + output.Consume(100); var data = output.WrittenSpan.ToArray(); - output.GetMemory(32); - Assert.Equal(512, output.Capacity); + output.GetMemory(16); + Assert.InRange(output.Capacity, capacity * 2, int.MaxValue); Assert.Equal(data, output.WrittenSpan.ToArray()); - Assert.Equal(272, output.FreeCapacity); - Assert.Equal(240, output.UnconsumedWrittenCount); + Assert.Equal(capacity - 100, output.UnconsumedWrittenCount); } [Fact] - public void CapacityDoesIncreaseIfThereIsOnlyMinimalConsumedSpace() + public void ThrowsIfUsedAfterDisposed() { - var output = new ConsumableArrayBufferWriter(256); - WriteData(output, 256); - output.Consume(100); - var data = output.WrittenSpan.ToArray(); - output.GetMemory(16); - Assert.Equal(512, output.Capacity); - Assert.Equal(data, output.WrittenSpan.ToArray()); - Assert.Equal(356, output.FreeCapacity); - Assert.Equal(156, output.UnconsumedWrittenCount); + var buffer = new ConsumableArrayBufferWriter(); + buffer.Dispose(); + Assert.Throws(() => buffer.GetMemory()); + Assert.Throws(() => buffer.GetSpan()); } #region ArrayBufferWriterTests @@ -128,25 +146,25 @@ public void CapacityDoesIncreaseIfThereIsOnlyMinimalConsumedSpace() public void ArrayBufferWriter_Ctor() { { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); Assert.Equal(0, output.FreeCapacity); Assert.Equal(0, output.Capacity); Assert.Equal(0, output.UnconsumedWrittenCount); - Assert.True(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); - Assert.True(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); + Assert.True(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); + Assert.True(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); } { - var output = new ConsumableArrayBufferWriter(200); + var output = new ConsumableArrayBufferWriter(200); Assert.True(output.FreeCapacity >= 200); Assert.True(output.Capacity >= 200); Assert.Equal(0, output.UnconsumedWrittenCount); - Assert.True(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); - Assert.True(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); + Assert.True(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); + Assert.True(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); } { - ConsumableArrayBufferWriter output = default; + ConsumableArrayBufferWriter output = default; Assert.Null(output); } } @@ -154,26 +172,26 @@ public void ArrayBufferWriter_Ctor() [Fact] public void Invalid_Ctor() { - Assert.Throws(() => new ConsumableArrayBufferWriter(0)); - Assert.Throws(() => new ConsumableArrayBufferWriter(-1)); - Assert.Throws(() => new ConsumableArrayBufferWriter(int.MaxValue)); + Assert.Throws(() => new ConsumableArrayBufferWriter(0)); + Assert.Throws(() => new ConsumableArrayBufferWriter(-1)); + Assert.Throws(() => new ConsumableArrayBufferWriter(int.MaxValue)); } [Fact] public void Clear() { - var output = new ConsumableArrayBufferWriter(256); + var output = new ConsumableArrayBufferWriter(256); var previousAvailable = output.FreeCapacity; WriteData(output, 2); Assert.True(output.FreeCapacity < previousAvailable); Assert.True(output.UnconsumedWrittenCount > 0); - Assert.False(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); - Assert.False(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); + Assert.False(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); + Assert.False(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); Assert.True(output.WrittenSpan.SequenceEqual(output.WrittenMemory.Span)); output.Clear(); Assert.Equal(0, output.UnconsumedWrittenCount); - Assert.True(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); - Assert.True(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); + Assert.True(ReadOnlySpan.Empty.SequenceEqual(output.WrittenSpan)); + Assert.True(ReadOnlyMemory.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); Assert.Equal(previousAvailable, output.FreeCapacity); Assert.Equal(0, output.UnconsumedWrittenCount); } @@ -182,7 +200,7 @@ public void Clear() public void Advance() { { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); var capacity = output.Capacity; Assert.Equal(capacity, output.FreeCapacity); output.Advance(output.FreeCapacity); @@ -191,7 +209,7 @@ public void Advance() } { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); output.Advance(output.Capacity); Assert.Equal(output.Capacity, output.UnconsumedWrittenCount); Assert.Equal(0, output.FreeCapacity); @@ -201,7 +219,7 @@ public void Advance() } { - var output = new ConsumableArrayBufferWriter(256); + var output = new ConsumableArrayBufferWriter(256); WriteData(output, 2); var previousMemory = output.WrittenMemory; var previousSpan = output.WrittenSpan; @@ -213,7 +231,7 @@ public void Advance() } { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); _ = output.GetSpan(20); WriteData(output, 10); var previousMemory = output.WrittenMemory; @@ -230,7 +248,7 @@ public void Advance() [Fact] public void AdvanceZero() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 2); Assert.Equal(2, output.UnconsumedWrittenCount); var previousMemory = output.WrittenMemory; @@ -247,13 +265,13 @@ public void AdvanceZero() public void InvalidAdvance() { { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); Assert.Throws(() => output.Advance(-1)); Assert.Throws(() => output.Advance(output.Capacity + 1)); } { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 100); Assert.Throws(() => output.Advance(output.FreeCapacity + 1)); } @@ -262,7 +280,7 @@ public void InvalidAdvance() [Fact] public void GetSpan_DefaultCtor() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); var span = output.GetSpan(); Assert.Equal(256, span.Length); } @@ -271,17 +289,17 @@ public void GetSpan_DefaultCtor() [MemberData(nameof(SizeHints))] public void GetSpanWithSizeHint_DefaultCtor(int sizeHint) { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); var span = output.GetSpan(sizeHint); - Assert.Equal(sizeHint <= 256 ? 256 : sizeHint, span.Length); + Assert.InRange(span.Length, sizeHint, int.MaxValue); } [Fact] public void GetSpan_InitSizeCtor() { - var output = new ConsumableArrayBufferWriter(100); + var output = new ConsumableArrayBufferWriter(100); var span = output.GetSpan(); - Assert.Equal(100, span.Length); + Assert.InRange(span.Length, 100, int.MaxValue); } [Theory] @@ -289,22 +307,22 @@ public void GetSpan_InitSizeCtor() public void GetSpanWithSizeHint_InitSizeCtor(int sizeHint) { { - var output = new ConsumableArrayBufferWriter(256); + var output = new ConsumableArrayBufferWriter(256); var span = output.GetSpan(sizeHint); - Assert.Equal(sizeHint <= 256 ? 256 : sizeHint + 256, span.Length); + Assert.InRange(span.Length, sizeHint, int.MaxValue); } { - var output = new ConsumableArrayBufferWriter(1000); + var output = new ConsumableArrayBufferWriter(1000); var span = output.GetSpan(sizeHint); - Assert.Equal(sizeHint <= 1000 ? 1000 : sizeHint + 1000, span.Length); + Assert.InRange(span.Length, sizeHint <= 1000 ? 1000 : sizeHint + 1000, int.MaxValue); } } [Fact] public void GetMemory_DefaultCtor() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); var memory = output.GetMemory(); Assert.Equal(256, memory.Length); } @@ -313,17 +331,17 @@ public void GetMemory_DefaultCtor() [MemberData(nameof(SizeHints))] public void GetMemoryWithSizeHint_DefaultCtor(int sizeHint) { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); var memory = output.GetMemory(sizeHint); - Assert.Equal(sizeHint <= 256 ? 256 : sizeHint, memory.Length); + Assert.InRange(memory.Length, sizeHint, int.MaxValue); } [Fact] public void GetMemory_InitSizeCtor() { - var output = new ConsumableArrayBufferWriter(100); + var output = new ConsumableArrayBufferWriter(100); var memory = output.GetMemory(); - Assert.Equal(100, memory.Length); + Assert.InRange(memory.Length, 100, int.MaxValue); } [Theory] @@ -331,15 +349,15 @@ public void GetMemory_InitSizeCtor() public void GetMemoryWithSizeHint_InitSizeCtor(int sizeHint) { { - var output = new ConsumableArrayBufferWriter(256); + var output = new ConsumableArrayBufferWriter(256); var memory = output.GetMemory(sizeHint); - Assert.Equal(sizeHint <= 256 ? 256 : sizeHint + 256, memory.Length); + Assert.InRange(memory.Length, sizeHint, int.MaxValue); } { - var output = new ConsumableArrayBufferWriter(1000); + var output = new ConsumableArrayBufferWriter(1000); var memory = output.GetMemory(sizeHint); - Assert.Equal(sizeHint <= 1000 ? 1000 : sizeHint + 1000, memory.Length); + Assert.InRange(memory.Length, sizeHint <= 1000 ? 1000 : sizeHint + 1000, int.MaxValue); } } @@ -349,7 +367,7 @@ public void GetMemoryWithSizeHint_InitSizeCtor(int sizeHint) public void GetMemoryAndSpan() { { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 2); var span = output.GetSpan(); var memory = output.GetMemory(); @@ -357,54 +375,37 @@ public void GetMemoryAndSpan() Assert.True(span.Length > 0); Assert.True(memorySpan.Length > 0); Assert.Equal(span.Length, memorySpan.Length); - for (var i = 0; i < span.Length; i++) - { - Assert.Equal(default, span[i]); - Assert.Equal(default, memorySpan[i]); - } } { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 2); var writtenSoFarMemory = output.WrittenMemory; var writtenSoFar = output.WrittenSpan; Assert.True(writtenSoFarMemory.Span.SequenceEqual(writtenSoFar)); - var previousAvailable = output.FreeCapacity; var span = output.GetSpan(500); Assert.True(span.Length >= 500); Assert.True(output.FreeCapacity >= 500); - Assert.True(output.FreeCapacity > previousAvailable); Assert.Equal(writtenSoFar.Length, output.UnconsumedWrittenCount); - Assert.False(writtenSoFar.SequenceEqual(span.Slice(0, output.UnconsumedWrittenCount))); var memory = output.GetMemory(); var memorySpan = memory.Span; Assert.True(span.Length >= 500); Assert.True(memorySpan.Length >= 500); Assert.Equal(span.Length, memorySpan.Length); - for (var i = 0; i < span.Length; i++) - { - Assert.Equal(default, span[i]); - Assert.Equal(default, memorySpan[i]); - } memory = output.GetMemory(500); memorySpan = memory.Span; Assert.True(memorySpan.Length >= 500); Assert.Equal(span.Length, memorySpan.Length); - for (var i = 0; i < memorySpan.Length; i++) - { - Assert.Equal(default, memorySpan[i]); - } } } [Fact] public void GetSpanShouldAtleastDoubleWhenGrowing() { - var output = new ConsumableArrayBufferWriter(256); + var output = new ConsumableArrayBufferWriter(256); WriteData(output, 100); var previousAvailable = output.FreeCapacity; @@ -419,7 +420,7 @@ public void GetSpanShouldAtleastDoubleWhenGrowing() public void GetSpanOnlyGrowsAboveThreshold() { { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); _ = output.GetSpan(); var previousAvailable = output.FreeCapacity; @@ -431,7 +432,7 @@ public void GetSpanOnlyGrowsAboveThreshold() } { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); _ = output.GetSpan(10); var previousAvailable = output.FreeCapacity; @@ -446,14 +447,12 @@ public void GetSpanOnlyGrowsAboveThreshold() [Fact] public void InvalidGetMemoryAndSpan() { - var output = new ConsumableArrayBufferWriter(); + var output = new ConsumableArrayBufferWriter(); WriteData(output, 2); Assert.Throws(() => output.GetSpan(-1)); Assert.Throws(() => output.GetMemory(-1)); } - protected abstract void WriteData(IBufferWriter bufferWriter, int numBytes); - public static IEnumerable SizeHints { get @@ -476,11 +475,8 @@ public static IEnumerable SizeHints } } #endregion - } - public class ConsumableArrayBufferWriterTests_Byte : ConsumableArrayBufferWriterTests - { - protected override void WriteData(IBufferWriter bufferWriter, int numBytes) + private void WriteData(IBufferWriter bufferWriter, int numBytes) { var outputSpan = bufferWriter.GetSpan(numBytes); Assert.True(outputSpan.Length >= numBytes); @@ -493,35 +489,4 @@ protected override void WriteData(IBufferWriter bufferWriter, int numBytes bufferWriter.Advance(numBytes); } } - - public class ConsumableArrayBufferWriterTests_String : ConsumableArrayBufferWriterTests - { - protected override void WriteData(IBufferWriter bufferWriter, int numStrings) - { - var outputSpan = bufferWriter.GetSpan(numStrings); - Debug.Assert(outputSpan.Length >= numStrings); - var random = new Random(42); - - var data = new string[numStrings]; - - for (var i = 0; i < numStrings; i++) - { - var length = random.Next(5, 10); - data[i] = GetRandomString(random, length, 32, 127); - } - - data.CopyTo(outputSpan); - - bufferWriter.Advance(numStrings); - } - private static string GetRandomString(Random r, int length, int minCodePoint, int maxCodePoint) - { - var sb = new StringBuilder(length); - while (length-- != 0) - { - sb.Append((char)r.Next(minCodePoint, maxCodePoint)); - } - return sb.ToString(); - } - } }