예제 #1
0
        public void ComparisonMembers_NotEquals()
        {
            var position  = new SequencePosition(null, 2);
            var position2 = new SequencePosition(2, 2);

            Assert.False(position.Equals(position2));
            Assert.False(position.Equals((object)position2));
            Assert.NotEqual(position.GetHashCode(), position2.GetHashCode());
        }
예제 #2
0
        public void ComparisonMembers_IntSegment()
        {
            var position  = new SequencePosition(2, 2);
            var position2 = new SequencePosition(2, 2);

            Assert.True(position.Equals(position2));
            Assert.True(position.Equals((object)position2));
            Assert.Equal(position.GetHashCode(), position2.GetHashCode());
        }
예제 #3
0
        public void ComparisonMembers_NotNullSegment()
        {
            var segment   = new object();
            var position  = new SequencePosition(segment, 2);
            var position2 = new SequencePosition(segment, 2);

            Assert.True(position == position2);
            Assert.True(position.Equals(position2));
            Assert.True(position.Equals((object)position2));
            Assert.False(position != position2);
            Assert.Equal(position.GetHashCode(), position2.GetHashCode());
        }
        public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
        {
            if (!_isReading)
            {
                throw new InvalidOperationException("No reading operation to complete.");
            }

            _isReading = false;

            if (_readCompleted)
            {
                // If the old stored _readResult was canceled, it's already been observed. Do not store a canceled read result permanently.
                _readResult = new ReadResult(_readResult.Buffer.Slice(consumed, _readResult.Buffer.End), isCanceled: false, isCompleted: true);

                if (!_finalAdvanceCalled && _readResult.Buffer.Length == 0)
                {
                    _context.Input.AdvanceTo(consumed);
                    _finalAdvanceCalled = true;
                    _context.OnTrailersComplete();
                }

                return;
            }

            // If consumed != examined, we cannot reset _context.Input back to a non-reading state after the next call to ReadAsync
            // simply by calling _context.Input.AdvanceTo(_readResult.Buffer.Start) because the DefaultPipeReader will complain that
            // "The examined position cannot be less than the previously examined position."
            _cannotResetInputPipe   = !consumed.Equals(examined);
            _unexaminedInputLength -= TrackConsumedAndExaminedBytes(_readResult, consumed, examined);
            _context.Input.AdvanceTo(consumed, examined);
        }
        public ReadOnlyMemory <byte> MakeFrame(ReadOnlySequence <byte> seq)
        {
            // cached frame
            if (_lastFrameStart.Equals(seq.Start) && _lastFrameEnd.Equals(seq.End))
            {
                Debug.WriteLine("Hit cached frame");
                return(_lastFrame);
            }

            _lastFrameStart = seq.Start;
            _lastFrameEnd   = seq.End;

            if (seq.IsSingleSegment)
            {
                Debug.WriteLine("Frame is single segement");
                _lastFrame = seq.First;
                return(seq.First);
            }

            Debug.WriteLine("Copy frame data into single Memory");
            Memory <byte> ret = new byte[seq.Length];
            var           ptr = 0;

            foreach (var mem in seq)
            {
                mem.CopyTo(ret.Slice(ptr));
                ptr += mem.Length;
            }

            _lastFrame = ret;
            return(ret);
        }
        private static void Byte_MultiSegment(int bufSize, int bufOffset)
        {
            var segment1 = new BufferSegment <byte>(new byte[bufSize / 10]);
            BufferSegment <byte> segment2 = segment1;

            for (int j = 0; j < 10; j++)
            {
                segment2 = segment2.Append(new byte[bufSize / 10]);
            }
            var buffer           = new ReadOnlySequence <byte>(segment1, bufOffset, segment2, bufSize / 10 - bufOffset);
            int offset           = (int)buffer.Length / 10;
            SequencePosition end = buffer.GetPosition(0, buffer.End);

            foreach (BenchmarkIteration iteration in Benchmark.Iterations)
            {
                int localInt = 0;
                using (iteration.StartMeasurement())
                {
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        SequencePosition pos = buffer.Start;
                        while (!pos.Equals(end))
                        {
                            pos       = buffer.GetPosition(offset, pos);
                            localInt ^= pos.GetInteger();
                        }
                    }
                }
                _volatileInt = localInt;
            }
        }
        private static void String(int bufSize, int bufOffset)
        {
            ReadOnlyMemory <char> memory = new string('a', bufSize).AsMemory();

            memory = memory.Slice(bufOffset, bufSize - 2 * bufOffset);
            var buffer           = new ReadOnlySequence <char>(memory);
            int offset           = (int)buffer.Length / 10;
            SequencePosition end = buffer.GetPosition(0, buffer.End);

            foreach (BenchmarkIteration iteration in Benchmark.Iterations)
            {
                int localInt = 0;
                using (iteration.StartMeasurement())
                {
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        SequencePosition pos = buffer.Start;
                        while (!pos.Equals(end))
                        {
                            pos       = buffer.GetPosition(offset, pos);
                            localInt ^= pos.GetInteger();
                        }
                    }
                }
                _volatileInt = localInt;
            }
        }
예제 #8
0
 OperationStatus NotEnoughData(TokenType tokenType)
 {
     CurrentToken = new Token(tokenType, _reader.SliceToNow(_tokenStart));
     _reader.Rewind(_rewindCount);
     Debug.Assert(_tokenStart.Equals(_reader.Position));
     Reset();
     return(OperationStatus.NeedMoreData);
 }
예제 #9
0
        protected long OnAdvance(ReadResult readResult, SequencePosition consumed, SequencePosition examined)
        {
            // This code path is fairly hard to understand so let's break it down with an example
            // ReadAsync returns a ReadResult of length 50.
            // Advance(25, 40). The examined length would be 40 and consumed length would be 25.
            // _totalExaminedInPreviousReadResult starts at 0. newlyExamined is 40.
            // OnDataRead is called with length 40.
            // _totalExaminedInPreviousReadResult is now 40 - 25 = 15.

            // The next call to ReadAsync returns 50 again
            // Advance(5, 5) is called
            // newlyExamined is 5 - 15, or -10.
            // Update _totalExaminedInPreviousReadResult to 10 as we consumed 5.

            // The next call to ReadAsync returns 50 again
            // _totalExaminedInPreviousReadResult is 10
            // Advance(50, 50) is called
            // newlyExamined = 50 - 10 = 40
            // _totalExaminedInPreviousReadResult is now 50
            // _totalExaminedInPreviousReadResult is finally 0 after subtracting consumedLength.

            long examinedLength, consumedLength, totalLength;

            if (consumed.Equals(examined))
            {
                examinedLength = readResult.Buffer.Slice(readResult.Buffer.Start, examined).Length;
                consumedLength = examinedLength;
            }
            else
            {
                consumedLength = readResult.Buffer.Slice(readResult.Buffer.Start, consumed).Length;
                examinedLength = consumedLength + readResult.Buffer.Slice(consumed, examined).Length;
            }

            if (examined.Equals(readResult.Buffer.End))
            {
                totalLength = examinedLength;
            }
            else
            {
                totalLength = readResult.Buffer.Length;
            }

            var newlyExamined = examinedLength - _examinedUnconsumedBytes;

            if (newlyExamined > 0)
            {
                OnDataRead(newlyExamined);
                _examinedUnconsumedBytes += newlyExamined;
            }

            _examinedUnconsumedBytes -= consumedLength;
            _alreadyTimedBytes        = totalLength - consumedLength;

            return(newlyExamined);
        }
        public async Task ThrowingFromStreamCallsAdvanceToWithStartOfLastReadResult(int throwAfterNWrites)
        {
            var wrappedPipeReader = new TestPipeReader(PipeReader);

            var  stream = new ThrowAfterNWritesStream(throwAfterNWrites);
            Task task   = wrappedPipeReader.CopyToAsync(stream);

            Pipe.Writer.WriteEmpty(10);
            await Pipe.Writer.FlushAsync();

            // Write twice for the test case where the stream throws on the second write.
            Pipe.Writer.WriteEmpty(10);
            await Pipe.Writer.FlushAsync();

            await Assert.ThrowsAsync <InvalidOperationException>(() => task);

            SequencePosition startPosition = wrappedPipeReader.LastReadResult.Buffer.Start;

            Assert.NotNull(startPosition.GetObject());
            Assert.True(startPosition.Equals(wrappedPipeReader.LastConsumed));
            Assert.True(startPosition.Equals(wrappedPipeReader.LastExamined));
        }
예제 #11
0
        /// <inheritdoc />
        public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
        {
            ThrowIfCompleted();

            // Fast path: did we consume everything?
            if (consumed.Equals(_sequence.End))
            {
                _sequence = ReadOnlySequence <byte> .Empty;
                return;
            }

            _sequence = _sequence.Slice(consumed);
        }
예제 #12
0
        protected async Task ReadPipeAsync(PipeReader reader)
        {
            while (true)
            {
                var result = await reader.ReadAsync();

                var buffer = result.Buffer;

                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;

                try
                {
                    if (result.IsCanceled)
                    {
                        break;
                    }

                    var completed = result.IsCompleted;

                    while (true)
                    {
                        var package = ReaderBuffer(buffer, out consumed, out examined);

                        if (package != null)
                        {
                            await OnPackageReceived(package);
                        }

                        if (examined.Equals(buffer.End))
                        {
                            break;
                        }

                        buffer = buffer.Slice(examined);
                    }

                    if (completed)
                    {
                        break;
                    }
                }
                finally
                {
                    reader.AdvanceTo(consumed, examined);
                }
            }

            reader.Complete();
        }
    public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
    {
        if (!_isReading)
        {
            throw new InvalidOperationException("No reading operation to complete.");
        }

        _isReading = false;

        // The current body is read, though there might be more bytes to read on the stream with pipelining
        if (_readCompleted)
        {
            if (!_finalAdvanceCalled && consumed.Equals(_readResult.Buffer.End))
            {
                // Don't reference the old buffer as it will be released by the pipe afer calling AdvancedTo
                _readResult = new ReadResult(new ReadOnlySequence <byte>(), isCanceled: false, isCompleted: true);

                _context.Input.AdvanceTo(consumed);
                _finalAdvanceCalled = true;
                _context.OnTrailersComplete();
            }
            else
            {
                // If the old stored _readResult was canceled, it's already been observed. Do not store a canceled read result permanently.
                _readResult = new ReadResult(_readResult.Buffer.Slice(consumed, _readResult.Buffer.End), isCanceled: false, isCompleted: true);
            }

            return;
        }

        // If consumed != examined, we cannot reset _context.Input back to a non-reading state after the next call to ReadAsync
        // simply by calling _context.Input.AdvanceTo(_readResult.Buffer.Start) because the DefaultPipeReader will complain that
        // "The examined position cannot be less than the previously examined position."
        _cannotResetInputPipe   = !consumed.Equals(examined);
        _unexaminedInputLength -= TrackConsumedAndExaminedBytes(_readResult, consumed, examined);
        _context.Input.AdvanceTo(consumed, examined);
    }
예제 #14
0
        private int IterateGetPosition(ReadOnlySequence <T> sequence)
        {
            int consume = 0;

            SequencePosition position = sequence.Start;
            int offset           = (int)(sequence.Length / 10);
            SequencePosition end = sequence.GetPosition(0, sequence.End);

            while (!position.Equals(end))
            {
                position = sequence.GetPosition(offset, position);
                consume += position.GetInteger();
            }

            return(consume);
        }
예제 #15
0
        public override void AdvanceTo(SequencePosition consumed, SequencePosition examined)
        {
            // This code path is fairly hard to understand so let's break it down with an example
            // ReadAsync returns a ReadResult of length 50.
            // Advance(25, 40). The examined length would be 40 and consumed length would be 25.
            // _totalExaminedInPreviousReadResult starts at 0. newlyExamined is 40.
            // OnDataRead is called with length 40.
            // _totalExaminedInPreviousReadResult is now 40 - 25 = 15.

            // The next call to ReadAsync returns 50 again
            // Advance(5, 5) is called
            // newlyExamined is 5 - 15, or -10.
            // Update _totalExaminedInPreviousReadResult to 10 as we consumed 5.

            // The next call to ReadAsync returns 50 again
            // _totalExaminedInPreviousReadResult is 10
            // Advance(50, 50) is called
            // newlyExamined = 50 - 10 = 40
            // _totalExaminedInPreviousReadResult is now 50
            // _totalExaminedInPreviousReadResult is finally 0 after subtracting consumedLength.

            long examinedLength;
            long consumedLength;

            if (consumed.Equals(examined))
            {
                examinedLength = _readResult.Buffer.Slice(_readResult.Buffer.Start, examined).Length;
                consumedLength = examinedLength;
            }
            else
            {
                consumedLength = _readResult.Buffer.Slice(_readResult.Buffer.Start, consumed).Length;
                examinedLength = consumedLength + _readResult.Buffer.Slice(consumed, examined).Length;
            }

            _context.RequestBodyPipe.Reader.AdvanceTo(consumed, examined);

            var newlyExamined = examinedLength - _alreadyExaminedInNextReadResult;

            if (newlyExamined > 0)
            {
                OnDataRead(newlyExamined);
                _alreadyExaminedInNextReadResult += newlyExamined;
            }

            _alreadyExaminedInNextReadResult -= consumedLength;
        }
예제 #16
0
        public async IAsyncEnumerable <object> Read()
        {
            ReadResult result;

            do
            {
                result = await reader.ReadAsync();

                var              buffer = result.Buffer;
                object?          item;
                SequencePosition finalPosition = buffer.Start;
                do
                {
                    (item, finalPosition) = FirstObjectFromBuffer(buffer.Slice(finalPosition));
                    if (item != null)
                    {
                        yield return(item);
                    }
                } while (item != null && !finalPosition.Equals(buffer.End));
                reader.AdvanceTo(finalPosition, buffer.End);
            } while (!(result.IsCompleted || result.IsCanceled));
        }
예제 #17
0
        protected async Task ReadPipeAsync(PipeReader reader)
        {
            while (true)
            {
                var result = await reader.ReadAsync();

                var buffer = result.Buffer;

                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;

                try
                {
                    if (result.IsCompleted)
                    {
                        break;
                    }

                    while (true)
                    {
                        ReaderBuffer(buffer, out consumed, out examined);

                        if (examined.Equals(buffer.End))
                        {
                            break;
                        }

                        buffer = buffer.Slice(examined);
                    }
                }
                finally
                {
                    reader.AdvanceTo(consumed, examined);
                }
            }

            reader.Complete();
        }
        private static void Byte_Array(int bufSize, int bufOffset)
        {
            var buffer           = new ReadOnlySequence <byte>(new byte[bufSize], bufOffset, bufSize - 2 * bufOffset);
            int offset           = (int)buffer.Length / 10;
            SequencePosition end = buffer.GetPosition(0, buffer.End);

            foreach (BenchmarkIteration iteration in Benchmark.Iterations)
            {
                int localInt = 0;
                using (iteration.StartMeasurement())
                {
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        SequencePosition pos = buffer.Start;
                        while (!pos.Equals(end))
                        {
                            pos       = buffer.GetPosition(offset, pos);
                            localInt ^= pos.GetInteger();
                        }
                    }
                }
                _volatileInt = localInt;
            }
        }
예제 #19
0
        protected async Task ReadPipeAsync(PipeReader reader)
        {
            while (true)
            {
                var result = await reader.ReadAsync();

                var buffer = result.Buffer;

                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;

                try
                {
                    if (result.IsCanceled)
                    {
                        break;
                    }

                    var completed = result.IsCompleted;

                    while (true)
                    {
                        var package = ReaderBuffer(buffer, out consumed, out examined);

                        if (package != null)
                        {
                            await OnPackageReceived(package);
                        }

                        var maxPackageLength = Options.MaxPackageLength;

                        if (maxPackageLength > 0 && buffer.Length > maxPackageLength)
                        {
                            Logger.LogError($"Package cannot be larger than {maxPackageLength}.");
                            completed = true;
                            // close the the connection directly
                            Close();
                            break;
                        }

                        if (examined.Equals(buffer.End))
                        {
                            break;
                        }

                        buffer = buffer.Slice(examined);
                    }

                    if (completed)
                    {
                        break;
                    }
                }
                finally
                {
                    reader.AdvanceTo(consumed, examined);
                }
            }

            reader.Complete();
        }