示例#1
0
    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);
    }
示例#2
0
    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]);
    }
示例#3
0
    public void Advance_TooFar()
    {
        var           seq  = new Sequence <char>();
        Memory <char> mem1 = seq.GetMemory(3);

        Assert.Throws <ArgumentOutOfRangeException>(() => seq.Advance(mem1.Length + 1));
    }
示例#4
0
            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);
            }
示例#5
0
    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);
    }
示例#7
0
    public void Advance_InvalidArgs()
    {
        var           seq  = new Sequence <char>();
        Memory <char> mem1 = seq.GetMemory(3);

        Assert.Throws <ArgumentOutOfRangeException>(() => seq.Advance(-1));
    }
示例#8
0
    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);
    }
示例#9
0
        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);
        }
示例#10
0
    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()));
    }
示例#11
0
    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);
    }
示例#12
0
    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);
                }
            }
示例#15
0
    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());
    }
示例#16
0
    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));
            }
示例#19
0
    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);
        }
示例#21
0
    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);
    }
示例#23
0
    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);
    }
示例#24
0
        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);
        }
示例#26
0
        /// <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);
            }
        }
示例#27
0
            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);
            }
示例#28
0
    public void Advance_BeforeGetMemory()
    {
        var seq = new Sequence <char>();

        Assert.Throws <InvalidOperationException>(() => seq.Advance(1));
    }