未验证 提交 bb9ba7ab 编写于 作者: A Alexander Radchenko 提交者: GitHub

Added ArrayBufferWriter<T>.ResetWrittenCount() (#88009)

Co-authored-by: NDavid Cantú <dacantu@microsoft.com>
上级 64a67710
...@@ -81,8 +81,15 @@ public ArrayBufferWriter(int initialCapacity) ...@@ -81,8 +81,15 @@ public ArrayBufferWriter(int initialCapacity)
/// Clears the data written to the underlying buffer. /// Clears the data written to the underlying buffer.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// You must clear the <see cref="ArrayBufferWriter{T}"/> before trying to re-use it. /// <para>
/// You must reset or clear the <see cref="ArrayBufferWriter{T}"/> before trying to re-use it.
/// </para>
/// <para>
/// The <see cref="ResetWrittenCount"/> method is faster since it only sets to zero the writer's index
/// while the <see cref="Clear"/> method additionally zeroes the content of the underlying buffer.
/// </para>
/// </remarks> /// </remarks>
/// <seealso cref="ResetWrittenCount"/>
public void Clear() public void Clear()
{ {
Debug.Assert(_buffer.Length >= _index); Debug.Assert(_buffer.Length >= _index);
...@@ -90,6 +97,20 @@ public void Clear() ...@@ -90,6 +97,20 @@ public void Clear()
_index = 0; _index = 0;
} }
/// <summary>
/// Resets the data written to the underlying buffer without zeroing its content.
/// </summary>
/// <remarks>
/// <para>
/// You must reset or clear the <see cref="ArrayBufferWriter{T}"/> before trying to re-use it.
/// </para>
/// <para>
/// If you reset the writer using the <see cref="ResetWrittenCount"/> method, the underlying buffer will not be cleared.
/// </para>
/// </remarks>
/// <seealso cref="Clear"/>
public void ResetWrittenCount() => _index = 0;
/// <summary> /// <summary>
/// Notifies <see cref="IBufferWriter{T}"/> that <paramref name="count"/> amount of data was written to the output <see cref="Span{T}"/>/<see cref="Memory{T}"/> /// Notifies <see cref="IBufferWriter{T}"/> that <paramref name="count"/> amount of data was written to the output <see cref="Span{T}"/>/<see cref="Memory{T}"/>
/// </summary> /// </summary>
...@@ -121,13 +142,21 @@ public void Advance(int count) ...@@ -121,13 +142,21 @@ public void Advance(int count)
/// Thrown when <paramref name="sizeHint"/> is negative. /// Thrown when <paramref name="sizeHint"/> is negative.
/// </exception> /// </exception>
/// <remarks> /// <remarks>
/// <para>
/// This will never return an empty <see cref="Memory{T}"/>. /// This will never return an empty <see cref="Memory{T}"/>.
/// </remarks> /// </para>
/// <remarks> /// <para>
/// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer.
/// </remarks> /// </para>
/// <remarks> /// <para>
/// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer.
/// </para>
/// <para>
/// If you reset the writer using the <see cref="ResetWrittenCount"/> method, this method may return a non-cleared <see cref="Memory{T}"/>.
/// </para>
/// <para>
/// If you clear the writer using the <see cref="Clear"/> method, this method will return a <see cref="Memory{T}"/> with its content zeroed.
/// </para>
/// </remarks> /// </remarks>
public Memory<T> GetMemory(int sizeHint = 0) public Memory<T> GetMemory(int sizeHint = 0)
{ {
...@@ -144,13 +173,21 @@ public Memory<T> GetMemory(int sizeHint = 0) ...@@ -144,13 +173,21 @@ public Memory<T> GetMemory(int sizeHint = 0)
/// Thrown when <paramref name="sizeHint"/> is negative. /// Thrown when <paramref name="sizeHint"/> is negative.
/// </exception> /// </exception>
/// <remarks> /// <remarks>
/// <para>
/// This will never return an empty <see cref="Span{T}"/>. /// This will never return an empty <see cref="Span{T}"/>.
/// </remarks> /// </para>
/// <remarks> /// <para>
/// There is no guarantee that successive calls will return the same buffer or the same-sized buffer. /// There is no guarantee that successive calls will return the same buffer or the same-sized buffer.
/// </remarks> /// </para>
/// <remarks> /// <para>
/// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer. /// You must request a new buffer after calling Advance to continue writing more data and cannot write to a previously acquired buffer.
/// </para>
/// <para>
/// If you reset the writer using the <see cref="ResetWrittenCount"/> method, this method may return a non-cleared <see cref="Span{T}"/>.
/// </para>
/// <para>
/// If you clear the writer using the <see cref="Clear"/> method, this method will return a <see cref="Span{T}"/> with its content zeroed.
/// </para>
/// </remarks> /// </remarks>
public Span<T> GetSpan(int sizeHint = 0) public Span<T> GetSpan(int sizeHint = 0)
{ {
......
...@@ -36,6 +36,7 @@ public sealed partial class ArrayBufferWriter<T> : System.Buffers.IBufferWriter< ...@@ -36,6 +36,7 @@ public sealed partial class ArrayBufferWriter<T> : System.Buffers.IBufferWriter<
public System.ReadOnlySpan<T> WrittenSpan { get { throw null; } } public System.ReadOnlySpan<T> WrittenSpan { get { throw null; } }
public void Advance(int count) { } public void Advance(int count) { }
public void Clear() { } public void Clear() { }
public void ResetWrittenCount() { }
public System.Memory<T> GetMemory(int sizeHint = 0) { throw null; } public System.Memory<T> GetMemory(int sizeHint = 0) { throw null; }
public System.Span<T> GetSpan(int sizeHint = 0) { throw null; } public System.Span<T> GetSpan(int sizeHint = 0) { throw null; }
} }
......
...@@ -22,13 +22,15 @@ protected override void WriteData(IBufferWriter<byte> bufferWriter, int numBytes ...@@ -22,13 +22,15 @@ protected override void WriteData(IBufferWriter<byte> bufferWriter, int numBytes
bufferWriter.Advance(numBytes); bufferWriter.Advance(numBytes);
} }
[Fact] [Theory]
public void WriteAndCopyToStream() [InlineData(true)]
[InlineData(false)]
public void WriteAndCopyToStream(bool clearContent)
{ {
var output = new ArrayBufferWriter<byte>(); ArrayBufferWriter<byte> output = new();
WriteData(output, 100); WriteData(output, 100);
using var memStream = new MemoryStream(100); using MemoryStream memStream = new(100);
Assert.Equal(100, output.WrittenCount); Assert.Equal(100, output.WrittenCount);
...@@ -40,13 +42,23 @@ public void WriteAndCopyToStream() ...@@ -40,13 +42,23 @@ public void WriteAndCopyToStream()
Assert.True(transientSpan.SequenceEqual(transientMemory.Span)); Assert.True(transientSpan.SequenceEqual(transientMemory.Span));
Assert.True(transientSpan[0] != 0); Assert.True(transientSpan[0] != 0);
byte expectedFirstByte = transientSpan[0];
memStream.Write(transientSpan.ToArray(), 0, transientSpan.Length); memStream.Write(transientSpan.ToArray(), 0, transientSpan.Length);
output.Clear();
if (clearContent)
Assert.True(transientSpan[0] == 0); {
Assert.True(transientMemory.Span[0] == 0); expectedFirstByte = 0;
output.Clear();
}
else
{
output.ResetWrittenCount();
}
Assert.Equal(expectedFirstByte, transientSpan[0]);
Assert.Equal(expectedFirstByte, transientMemory.Span[0]);
Assert.Equal(0, output.WrittenCount); Assert.Equal(0, output.WrittenCount);
byte[] streamOutput = memStream.ToArray(); byte[] streamOutput = memStream.ToArray();
...@@ -58,13 +70,15 @@ public void WriteAndCopyToStream() ...@@ -58,13 +70,15 @@ public void WriteAndCopyToStream()
Assert.True(outputSpan.SequenceEqual(streamOutput)); Assert.True(outputSpan.SequenceEqual(streamOutput));
} }
[Fact] [Theory]
public async Task WriteAndCopyToStreamAsync() [InlineData(true)]
[InlineData(false)]
public async Task WriteAndCopyToStreamAsync(bool clearContent)
{ {
var output = new ArrayBufferWriter<byte>(); ArrayBufferWriter<byte> output = new();
WriteData(output, 100); WriteData(output, 100);
using var memStream = new MemoryStream(100); using MemoryStream memStream = new(100);
Assert.Equal(100, output.WrittenCount); Assert.Equal(100, output.WrittenCount);
...@@ -73,11 +87,21 @@ public async Task WriteAndCopyToStreamAsync() ...@@ -73,11 +87,21 @@ public async Task WriteAndCopyToStreamAsync()
ReadOnlyMemory<byte> transient = output.WrittenMemory; ReadOnlyMemory<byte> transient = output.WrittenMemory;
Assert.True(transient.Span[0] != 0); Assert.True(transient.Span[0] != 0);
byte expectedFirstByte = transient.Span[0];
await memStream.WriteAsync(transient.ToArray(), 0, transient.Length); await memStream.WriteAsync(transient.ToArray(), 0, transient.Length);
output.Clear();
Assert.True(transient.Span[0] == 0); if (clearContent)
{
expectedFirstByte = 0;
output.Clear();
}
else
{
output.ResetWrittenCount();
}
Assert.True(transient.Span[0] == expectedFirstByte);
Assert.Equal(0, output.WrittenCount); Assert.Equal(0, output.WrittenCount);
byte[] streamOutput = memStream.ToArray(); byte[] streamOutput = memStream.ToArray();
......
...@@ -57,7 +57,45 @@ public void Clear() ...@@ -57,7 +57,45 @@ public void Clear()
Assert.False(ReadOnlySpan<T>.Empty.SequenceEqual(output.WrittenSpan)); Assert.False(ReadOnlySpan<T>.Empty.SequenceEqual(output.WrittenSpan));
Assert.False(ReadOnlyMemory<T>.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); Assert.False(ReadOnlyMemory<T>.Empty.Span.SequenceEqual(output.WrittenMemory.Span));
Assert.True(output.WrittenSpan.SequenceEqual(output.WrittenMemory.Span)); Assert.True(output.WrittenSpan.SequenceEqual(output.WrittenMemory.Span));
ReadOnlyMemory<T> transientMemory = output.WrittenMemory;
ReadOnlySpan<T> transientSpan = output.WrittenSpan;
T t0 = transientMemory.Span[0];
T t1 = transientSpan[1];
Assert.NotEqual(default, t0);
Assert.NotEqual(default, t1);
output.Clear(); output.Clear();
Assert.Equal(default, transientMemory.Span[0]);
Assert.Equal(default, transientSpan[1]);
Assert.Equal(0, output.WrittenCount);
Assert.True(ReadOnlySpan<T>.Empty.SequenceEqual(output.WrittenSpan));
Assert.True(ReadOnlyMemory<T>.Empty.Span.SequenceEqual(output.WrittenMemory.Span));
Assert.Equal(previousAvailable, output.FreeCapacity);
}
[Fact]
public void ResetWrittenCount()
{
var output = new ArrayBufferWriter<T>(256);
int previousAvailable = output.FreeCapacity;
WriteData(output, 2);
Assert.True(output.FreeCapacity < previousAvailable);
Assert.True(output.WrittenCount > 0);
Assert.False(ReadOnlySpan<T>.Empty.SequenceEqual(output.WrittenSpan));
Assert.False(ReadOnlyMemory<T>.Empty.Span.SequenceEqual(output.WrittenMemory.Span));
Assert.True(output.WrittenSpan.SequenceEqual(output.WrittenMemory.Span));
ReadOnlyMemory<T> transientMemory = output.WrittenMemory;
ReadOnlySpan<T> transientSpan = output.WrittenSpan;
T t0 = transientMemory.Span[0];
T t1 = transientSpan[1];
Assert.NotEqual(default, t0);
Assert.NotEqual(default, t1);
output.ResetWrittenCount();
Assert.Equal(t0, transientMemory.Span[0]);
Assert.Equal(t1, transientSpan[1]);
Assert.Equal(0, output.WrittenCount); Assert.Equal(0, output.WrittenCount);
Assert.True(ReadOnlySpan<T>.Empty.SequenceEqual(output.WrittenSpan)); Assert.True(ReadOnlySpan<T>.Empty.SequenceEqual(output.WrittenSpan));
Assert.True(ReadOnlyMemory<T>.Empty.Span.SequenceEqual(output.WrittenMemory.Span)); Assert.True(ReadOnlyMemory<T>.Empty.Span.SequenceEqual(output.WrittenMemory.Span));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册