public void AdvanceTo_PriorPositionInPriorBlock() { MockPool <char> mockPool = new MockPool <char>(); var seq = new Sequence <char>(mockPool); var mem1 = seq.GetMemory(3); mem1.Span.Fill('a'); seq.Advance(mem1.Length); var mem2 = seq.GetMemory(3); mem2.Span.Fill('b'); seq.Advance(mem2.Length); ReadOnlySequence <char> ros = seq; SequencePosition pos1 = ros.GetPosition(1); SequencePosition pos4 = ros.GetPosition(4); seq.AdvanceTo(pos4); Assert.Throws <ArgumentException>(() => seq.AdvanceTo(pos1)); ros = seq; Assert.Equal(2, ros.Length); Assert.Equal(ros.Length, seq.Length); }
public void AdvanceTo_InterweavedWith_Advance() { ReadOnlySpan <char> original = "abcdefg".ToCharArray(); ReadOnlySpan <char> later = "hijkl".ToCharArray(); var seq = new Sequence <char>(); var mem = seq.GetMemory(30); // Specify a size with enough space to store both buffers original.CopyTo(mem.Span); seq.Advance(original.Length); var originalRos = seq.AsReadOnlySequence; var origLastCharPosition = originalRos.GetPosition(originalRos.Length - 1); char origLastChar = originalRos.Slice(origLastCharPosition, 1).First.Span[0]; // "Consume" a few characters, but leave the origEnd an unconsumed position so it should be valid. seq.AdvanceTo(originalRos.GetPosition(3, originalRos.Start)); // Verify that the SequencePosition we saved before still represents the same character. Assert.Equal(origLastChar, seq.AsReadOnlySequence.Slice(origLastCharPosition, 1).First.Span[0]); // Append several characters mem = seq.GetMemory(later.Length); later.CopyTo(mem.Span); seq.Advance(later.Length); // Verify that the SequencePosition we saved before still represents the same character. Assert.Equal(origLastChar, seq.AsReadOnlySequence.Slice(origLastCharPosition, 1).First.Span[0]); }
public void Advance_TooFar() { var seq = new Sequence <char>(); Memory <char> mem1 = seq.GetMemory(3); Assert.Throws <ArgumentOutOfRangeException>(() => seq.Advance(mem1.Length + 1)); }
public bool TryReadNextChunk(Stream stream, [MaybeNullWhen(false)] out Sequence <byte>?chunk) { Span <byte> chunkLengthBuffer = stackalloc byte[sizeof(int)]; var chunkLengthBytesRead = stream.Read(chunkLengthBuffer); if (chunkLengthBytesRead == 0) { chunk = null; return(false); } var chunkLength = BitConverter.ToInt32(chunkLengthBuffer); var bufferSize = chunkLength > _chunkSize ? chunkLength : _chunkSize; chunk = new Sequence <byte>(ArrayPool <byte> .Shared); try { var buffer = chunk.GetSpan(bufferSize).Slice(0, chunkLength); var bytesRead = stream.Read(buffer); chunk.Advance(bytesRead); if (bytesRead < chunkLength) { throw new InvalidOperationException("Archive entry is corrupted"); } } catch { chunk.Dispose(); throw; } return(true); }
public void GetMemory_TwiceInARowRecyclesOldArray(int leadingBlocks) { MockMemoryPool <char> mockPool = new MockMemoryPool <char>(); var seq = new Sequence <char>(mockPool); seq.MinimumSpanLength = 1; for (int i = 0; i < leadingBlocks; i++) { seq.GetMemory(1); seq.Advance(1); } Memory <char> mem1 = seq.GetMemory(16); // This second request cannot be satisfied by the first one since it's larger. So the first should be freed. Memory <char> mem2 = seq.GetMemory(32); mockPool.AssertContents(mem1); // This third one *can* be satisfied by the 32 byte array allocation requested previously, so no recycling should take place. Memory <char> mem3 = seq.GetMemory(24); mockPool.AssertContents(mem1); }
public void AdvanceTo_PositionFromUnrelatedSequence() { MockPool <char> mockPool = new MockPool <char>(); var seqA = new Sequence <char>(mockPool); var seqB = new Sequence <char>(mockPool); var mem1 = seqA.GetMemory(3); mem1.Span.Fill('a'); seqA.Advance(mem1.Length); var mem2 = seqB.GetMemory(3); mem2.Span.Fill('b'); seqB.Advance(mem2.Length); ReadOnlySequence <char> rosA = seqA; ReadOnlySequence <char> rosB = seqB; var posB = rosB.GetPosition(2); Assert.Throws <ArgumentException>(() => seqA.AdvanceTo(posB)); Assert.Equal(3, seqA.AsReadOnlySequence.Length); Assert.Equal(3, seqB.AsReadOnlySequence.Length); }
public void Advance_InvalidArgs() { var seq = new Sequence <char>(); Memory <char> mem1 = seq.GetMemory(3); Assert.Throws <ArgumentOutOfRangeException>(() => seq.Advance(-1)); }
public async ValueTask <ReadOnlySequence <byte> > ReadAtLeastAsync(PipeReader reader, int minLength) { Requires.NotNull(reader, nameof(reader)); Requires.Range(minLength > 0, nameof(minLength)); var bytesReceived = new Sequence <byte>(); while (bytesReceived.Length < minLength) { var readResult = await reader.ReadAsync(this.TimeoutToken); foreach (var segment in readResult.Buffer) { var memory = bytesReceived.GetMemory(segment.Length); segment.CopyTo(memory); bytesReceived.Advance(segment.Length); } reader.AdvanceTo(readResult.Buffer.End); if (readResult.IsCompleted && bytesReceived.Length < minLength) { throw new EndOfStreamException($"PipeReader completed after reading {bytesReceived.Length} of the expected {minLength} bytes."); } } return(bytesReceived.AsReadOnlySequence); }
internal static void WriteRequestLine(ref Sequence <byte> buffer, string protocol, PipelineMethod method, ReadOnlySpan <byte> path) { if (protocol != "https") { throw new NotImplementedException(); } var segment = buffer.GetMemory().Span; int written = 0; if (method == PipelineMethod.Get) { s_get.CopyTo(segment); written = s_get.Length; } else if (method == PipelineMethod.Post) { s_post.CopyTo(segment); written = s_post.Length; } path.CopyTo(segment.Slice(written)); written += path.Length; s_http11CrLf.CopyTo(segment.Slice(written)); written += s_http11CrLf.Length; buffer.Advance(written); }
public void GetSpan_ReservesHeaderSpaceForWritingLater() { var seq = new Sequence <char>(); Span <char> headerSpan = seq.GetSpan(4); seq.Advance(4); Span <char> contentSpan = seq.GetSpan(10); "0123456789".AsSpan().CopyTo(contentSpan); seq.Advance(10); "abcd".AsSpan().CopyTo(headerSpan); Assert.Equal("abcd0123456789", new string(seq.AsReadOnlySequence.ToArray())); }
public void AdvanceTo_InterweavedWith_Advance2() { // use the mock pool so that we can predict the actual array size will not exceed what we ask for. var seq = new Sequence <int>(new MockPool <int>()); seq.GetSpan(10); seq.Advance(10); seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(3)); seq.GetSpan(10); seq.Advance(10); seq.GetSpan(10); seq.Advance(10); Assert.Equal(10 - 3 + 10 + 10, seq.AsReadOnlySequence.Length); }
public void Advance_EmptyBlock() { var seq = new Sequence <char>(); Memory <char> mem1 = seq.GetMemory(3); seq.Advance(0); Assert.True(seq.AsReadOnlySequence.IsEmpty); }
public void AdvanceTo_ReturnsArraysToPool() { MockPool <char> mockPool = new MockPool <char>(); var seq = new Sequence <char>(mockPool); var mem1 = seq.GetMemory(3); mem1.Span.Fill('a'); seq.Advance(mem1.Length); var mem2 = seq.GetMemory(3); mem2.Span.Fill('b'); seq.Advance(mem2.Length); var mem3 = seq.GetMemory(3); mem3.Span.Fill('c'); seq.Advance(mem3.Length); // Assert that the used arrays are not in the pool. Assert.Empty(mockPool.Contents); // Advance, but don't go beyond the first array. seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(mem1.Length - 1)); Assert.Empty(mockPool.Contents); // Now advance beyond the first array and assert that it has been returned to the pool. seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(1)); mockPool.AssertContents(mem1); // Skip past the second array. seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(mem2.Length)); mockPool.AssertContents(mem1, mem2); // Advance part way through the third array. seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(mem3.Length - 2)); mockPool.AssertContents(mem1, mem2); // Now advance to the end. seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(2)); Assert.True(seq.AsReadOnlySequence.IsEmpty); mockPool.AssertContents(mem1, mem2, mem3); }
public sealed override void AddHeader(HttpHeader header) { if (_endOfHeadersWritten) { throw new NotImplementedException("need to shift EOH"); } Span <byte> span = _requestBuffer.GetSpan(); while (true) { if (header.TryWrite(span, out var written)) { _requestBuffer.Advance(written); return; } span = _requestBuffer.GetSpan(span.Length * 2); } }
public void Advance_OneBlock() { var seq = new Sequence <char>(); Memory <char> mem1 = seq.GetMemory(3); mem1.Span[0] = 'a'; mem1.Span[1] = 'b'; Assert.True(seq.AsReadOnlySequence.IsEmpty); seq.Advance(2); Assert.Equal("ab".ToCharArray(), seq.AsReadOnlySequence.ToArray()); }
private static WeakReference StoreReferenceInSequence <T>(Sequence <T> seq) where T : class, new() { var o = new T(); var tracker = new WeakReference(o); var span = seq.GetSpan(5); span[0] = o; seq.Advance(1); return(tracker); }
public void TwoSegmentBuilder() { pool.ClearDiagnostics(); var sequence = new Sequence <byte>(pool); sequence.GetMemory(4096); sequence.Advance(4095); sequence.GetMemory(4096); sequence.Advance(4096); var ros = sequence.AsReadOnly(); Assert.False(ros.IsSingleSegment); Assert.AreEqual(4096 * 2 - 1, ros.Length); sequence.Dispose(); Assert.AreEqual(2, pool.TotalRented); Assert.AreEqual(0, pool.CurrentlyRented); }
internal override Task <Sequence <byte> > ReceiveAsync(Sequence <byte> buffer) { var response = _responses[_responseNumber++]; if (_responseNumber >= _responses.Length) { _responseNumber = 0; } var segment = buffer.GetMemory(response.Length); response.CopyTo(segment); buffer.Advance(response.Length); return(Task.FromResult(buffer)); }
public void Advance_TwoBlocks_Advance() { var seq = new Sequence <char>(); Memory <char> mem1 = seq.GetMemory(3); mem1.Span[0] = 'a'; mem1.Span[1] = 'b'; seq.Advance(2); Memory <char> mem2 = seq.GetMemory(2); mem2.Span[0] = 'c'; mem2.Span[1] = 'd'; seq.Advance(2); Assert.Equal("abcd".ToCharArray(), seq.AsReadOnlySequence.ToArray()); seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(1)); Assert.Equal("bcd".ToCharArray(), seq.AsReadOnlySequence.ToArray()); seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(2)); Assert.Equal("d".ToCharArray(), seq.AsReadOnlySequence.ToArray()); }
public void ThreeSegmentBuilder() { pool.ClearDiagnostics(); var builder = new Sequence <byte>(pool); builder.GetMemory(4096); builder.Advance(4095); builder.GetMemory(4096); builder.Advance(4096); builder.GetMemory(4096); builder.Advance(4095); var sequence = builder.AsReadOnly(); Assert.False(sequence.IsSingleSegment); Assert.AreEqual(4096 * 3 - 2, sequence.Length); builder.Dispose(); Assert.AreEqual(3, pool.TotalRented); Assert.AreEqual(0, pool.CurrentlyRented); }
public void AdvanceTo_InterweavedWith_Advance2() { // use the mock pool so that we can predict the actual array size will not exceed what we ask for. var seq = new Sequence <int>(new MockMemoryPool <int>()); var span = seq.GetSpan(10); Enumerable.Range(1, 10).ToArray().CopyTo(span); seq.Advance(10); seq.AdvanceTo(seq.AsReadOnlySequence.GetPosition(3)); span = seq.GetSpan(10); Enumerable.Range(11, 10).ToArray().CopyTo(span); seq.Advance(10); span = seq.GetSpan(10); Enumerable.Range(21, 10).ToArray().CopyTo(span); seq.Advance(10); this.Logger.WriteLine(string.Join(", ", seq.AsReadOnlySequence.ToArray())); Assert.Equal(Enumerable.Range(4, 27), seq.AsReadOnlySequence.ToArray()); Assert.Equal(10 - 3 + 10 + 10, seq.AsReadOnlySequence.Length); }
public void Dispose_ReturnsArraysToPool() { MockPool <char> mockPool = new MockPool <char>(); var seq = new Sequence <char>(mockPool); var expected = new List <Memory <char> >(); for (int i = 0; i < 3; i++) { var mem = seq.GetMemory(3); expected.Add(mem); seq.Advance(mem.Length); } seq.Dispose(); Assert.True(seq.AsReadOnlySequence.IsEmpty); mockPool.AssertContents(expected); }
public void Dispose_ReturnsArraysToPool_ArrayPool() { MockArrayPool <char> mockPool = new MockArrayPool <char>(); var seq = new Sequence <char>(mockPool); var expected = new List <char[]>(); for (int i = 0; i < 3; i++) { var mem = seq.GetMemory(3); Assumes.True(MemoryMarshal.TryGetArray <char>(mem, out var segment)); expected.Add(segment.Array); seq.Advance(mem.Length); } seq.Dispose(); Assert.True(seq.AsReadOnlySequence.IsEmpty); mockPool.AssertContents(expected); }
public static void WriteHeader(ref Sequence <byte> buffer, ReadOnlySpan <byte> headerName, ReadOnlySpan <byte> headerValue) { var segment = buffer.GetMemory().Span; int written = 0; headerName.CopyTo(segment); written += headerName.Length; segment.Slice(written)[0] = s_headerSeparator; written += 1; headerValue.CopyTo(segment.Slice(written)); written += headerValue.Length; s_crlf.CopyTo(segment.Slice(written)); written += s_crlf.Length; buffer.Advance(written); }
public void SingleSegmentBuilder() { pool.ClearDiagnostics(); var sequence = new Sequence <byte>(pool); var array = sequence.GetMemory(100); Assert.GreaterOrEqual(array.Length, 100); sequence.Advance(50); var ros = sequence.AsReadOnly(); Assert.True(ros.IsSingleSegment); Assert.AreEqual(50, ros.Length); sequence.Dispose(); Assert.AreEqual(1, pool.TotalRented); Assert.AreEqual(0, pool.CurrentlyRented); }
/// <inheritdoc /> protected override async ValueTask <JsonRpcMessage> ReadCoreAsync(CancellationToken cancellationToken) { using (var contentSequenceBuilder = new Sequence <byte>()) { #if NETCOREAPP2_1 ValueWebSocketReceiveResult result; #else WebSocketReceiveResult result; #endif do { Memory <byte> memory = contentSequenceBuilder.GetMemory(this.sizeHint); #if NETCOREAPP2_1 result = await this.WebSocket.ReceiveAsync(memory, cancellationToken).ConfigureAwait(false); contentSequenceBuilder.Advance(result.Count); #else ArrayPool <byte> pool = ArrayPool <byte> .Shared; byte[] segment = pool.Rent(this.sizeHint); try { result = await this.WebSocket.ReceiveAsync(new ArraySegment <byte>(segment), cancellationToken).ConfigureAwait(false); contentSequenceBuilder.Write(segment.AsSpan(0, result.Count)); } finally { pool.Return(segment); } #endif if (result.MessageType == WebSocketMessageType.Close) { await this.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed as requested.", CancellationToken.None).ConfigureAwait(false); return(null); } }while (!result.EndOfMessage); return(contentSequenceBuilder.AsReadOnlySequence.Length > 0 ? this.Formatter.Deserialize(contentSequenceBuilder) : null); } }
public bool TryReadNextChunk(Stream stream, out Sequence <byte>?chunk) { chunk = new Sequence <byte>(ArrayPool <byte> .Shared); try { var buffer = chunk.GetSpan(_chunkSize); var bytesRead = stream.Read(buffer); if (bytesRead == 0) { chunk.Dispose(); return(false); } chunk.Advance(bytesRead); } catch { chunk.Dispose(); throw; } return(true); }
public void Advance_BeforeGetMemory() { var seq = new Sequence <char>(); Assert.Throws <InvalidOperationException>(() => seq.Advance(1)); }