コード例 #1
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);
        }
コード例 #2
0
        private bool ParsePreface(ReadOnlySequence <byte> readableBuffer, out SequencePosition consumed, out SequencePosition examined)
        {
            consumed = readableBuffer.Start;
            examined = readableBuffer.End;

            if (readableBuffer.Length < ClientPreface.Length)
            {
                return(false);
            }

            var span = readableBuffer.IsSingleSegment
                ? readableBuffer.First.Span
                : readableBuffer.ToSpan();

            for (var i = 0; i < ClientPreface.Length; i++)
            {
                if (ClientPreface[i] != span[i])
                {
                    throw new Exception("Invalid HTTP/2 connection preface.");
                }
            }

            consumed = examined = readableBuffer.GetPosition(ClientPreface.Length);
            return(true);
        }
コード例 #3
0
        public async Task AdvanceWithGetPositionCrossingIntoWriteHeadWorks()
        {
            // Create two blocks
            Memory <byte> memory = _pipe.Writer.GetMemory(1);

            _pipe.Writer.Advance(memory.Length);
            memory = _pipe.Writer.GetMemory(1);
            _pipe.Writer.Advance(memory.Length);
            await _pipe.Writer.FlushAsync();

            // Read single block
            ReadResult readResult = await _pipe.Reader.ReadAsync();

            // Allocate more memory
            memory = _pipe.Writer.GetMemory(1);

            // Create position that would cross into write head
            ReadOnlySequence <byte> buffer   = readResult.Buffer;
            SequencePosition        position = buffer.GetPosition(buffer.Start, buffer.Length);

            // Return everything
            _pipe.Reader.AdvanceTo(position);

            // Advance writer
            _pipe.Writer.Advance(memory.Length);
            _pipe.Writer.Commit();
        }
コード例 #4
0
        public static bool ReadFrame(ReadOnlySequence <byte> readableBuffer, Http2Frame frame, uint maxFrameSize, out SequencePosition consumed, out SequencePosition examined)
        {
            consumed = readableBuffer.Start;
            examined = readableBuffer.End;

            if (readableBuffer.Length < Http2Frame.HeaderLength)
            {
                return(false);
            }

            var headerSlice = readableBuffer.Slice(0, Http2Frame.HeaderLength);

            headerSlice.CopyTo(frame.Raw);

            var payloadLength = frame.PayloadLength;

            if (payloadLength > maxFrameSize)
            {
                throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorFrameOverLimit(payloadLength, maxFrameSize), Http2ErrorCode.FRAME_SIZE_ERROR);
            }

            var frameLength = Http2Frame.HeaderLength + payloadLength;

            if (readableBuffer.Length < frameLength)
            {
                return(false);
            }

            readableBuffer.Slice(Http2Frame.HeaderLength, payloadLength).CopyTo(frame.Payload);
            consumed = examined = readableBuffer.GetPosition(frameLength);

            return(true);
        }
コード例 #5
0
        private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                var result = await reader.ReadAsync(cancellationToken);


                ReadOnlySequence <byte> buffer = result.Buffer;
                bool canParse = false;
                do
                {
                    canParse = _parser.CanParse(buffer);
                    if (canParse)
                    {
                        ParseResult messageParsed = await _parser.ParseAsync(buffer);

                        _whenMessageParsed.OnNext(messageParsed.CleanMessage);
                        buffer = buffer.Slice(buffer.GetPosition(1, messageParsed.EndPosition));
                    }
                }while (canParse);
                reader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }
            reader.Complete();
        }
コード例 #6
0
        public int Decode(ReadOnlySequence <byte> buffer)
        {
            DecoderHelper.ValidateSize(buffer.Length);
            if (isValueDecoded)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.FramingValueNotAvailable));
            }
            int bytesConsumed = 0;

            while (bytesConsumed < buffer.Length)
            {
                var data = buffer.First.Span;
                int next = data[0];
                value |= (next & 0x7F) << (index * 7);
                bytesConsumed++;
                if (index == LastIndex && (next & 0xF8) != 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataException(SR.FramingSizeTooLarge));
                }
                index++;
                if ((next & 0x80) == 0)
                {
                    isValueDecoded = true;
                    break;
                }
                buffer = buffer.Slice(buffer.GetPosition(1));
            }
            return(bytesConsumed);
        }
コード例 #7
0
        static async Task ReadFromPipe(PipeReader reader, Action <ReadOnlySequence <byte> > operation)
        {
            while (true)
            {
                var readResult = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer   = readResult.Buffer;
                SequencePosition?       position = null;
                do
                {
                    position = buffer.PositionOf((byte)'\n');
                    if (position != null)
                    {
                        var line = buffer.Slice(0, position.Value);
                        operation?.Invoke(line);
                        var next = buffer.GetPosition(1, position.Value); //等价于popstion+1因为需要包含'\n';
                        buffer = buffer.Slice(next);                      //跳过已经读取的数据;
                    }
                }while (position != null);
                //指示PipeReader已经消费了多少数据
                reader.AdvanceTo(buffer.Start, buffer.End);
                if (readResult.IsCompleted)
                {
                    break;
                }
            }
            reader.Complete();
        }
コード例 #8
0
        protected override (SegmentationStatus status, ReadOnlySequence <byte>?segment) Read(ReadOnlySequence <byte> buffer)
        {
            var startOfSegment = buffer.PositionOf(Start);

            if (startOfSegment != null)
            {
                var segment = buffer.Slice(startOfSegment.Value);

                var endOfSegment = segment.PositionOf(End);
                if (endOfSegment != null)
                {
                    var completeSegment = segment.Slice(0, segment.GetPosition(1, endOfSegment.Value));

                    if (this.Options.HasFlag(SegmentionOptions.SecondStartInvalid))
                    {
                        var secondStart = completeSegment.PositionOf(Start);
                        if (secondStart != null)
                        {
                            // Second start detected
                            return(SegmentationStatus.Invalid, buffer.Slice(0, secondStart.Value));
                        }
                    }

                    return(SegmentationStatus.Complete, completeSegment);
                }
                else if (this.MaxLength.HasValue && buffer.Length > this.MaxLength)
                {
                    var leftover = buffer.Length % this.MaxLength.Value;
                    buffer = buffer.Slice(0, buffer.GetPosition(-leftover, buffer.End));
                    return(SegmentationStatus.Invalid, buffer);
                }
            }

            return(SegmentationStatus.Incomplete, null);
        }
コード例 #9
0
ファイル: Connection.cs プロジェクト: MKenin/rmku
        static async Task ReadPipeAsync(IReadOnlyDictionary <ushort, IChannel> handlers, PipeReader reader)
        {
            while (true)
            {
                ReadResult result = await reader.ReadAsync();

                ReadOnlySequence <byte> buffer = result.Buffer;

                while (buffer.TryReadFrame(out Frame frame))
                {
                    //TODO: proper memory management instead of copy
                    var slice = buffer.Slice(Constants.HeaderSize, frame.ContentLength);

                    await handlers[frame.Channel].Handle(frame, ref slice);

                    var nextPart = buffer.GetPosition(frame.TotalLength);
                    buffer = buffer.Slice(nextPart);
                }
                ;

                reader.AdvanceTo(buffer.Start, buffer.End);

                if (result.IsCompleted)
                {
                    break;
                }
            }
            reader.Complete();
        }
コード例 #10
0
        public void GetOffset_MultiSegment_InvalidSequencePositionSegment()
        {
            ReadOnlySequence <T> buffer  = GetFourSegmentsReadOnlySequence();
            ReadOnlySequence <T> buffer2 = new ReadOnlySequence <T>(new T[50]);

            Assert.Throws <InvalidCastException>(() => buffer.GetOffset(buffer2.GetPosition(25)));
        }
コード例 #11
0
    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);
    }
コード例 #12
0
ファイル: MCConnectionHandler.cs プロジェクト: Tobi406/SM3
        private void HandlePacket(ReadOnlySequence <byte> buffer, MCConnectionContext ctx, IPacketQueue packetQueue)
        {
            var reader = _packetReaderFactory.CreateReader(buffer);
            var length = reader.ReadVarInt();

            if (length > reader.Buffer.Length || length < 1 /* 1 = small ID but no fields*/)
            {
                _logger.LogCritical($"Read Invalid length {length:X}. Aborting");
                ctx.Abort();
                return;
            }

            var lengthLength = buffer.Length - reader.Buffer.Length;

            reader = new MCPacketReader(reader.Buffer.Slice(0, length));
            var id = reader.ReadVarInt();

            using var packetIdScope = _logger.BeginScope($"Packet ID: {id:x2}");

            _packetHandler.HandlePacket(ctx, reader, packetQueue, id);

            // NOT IDEAL, but easiest
            var packetSize = length + lengthLength;

            ctx.Transport.Input.AdvanceTo(buffer.GetPosition(packetSize));
            _metrics.Measure.Histogram.Update(MetricsRegistry.ReadPacketSize, packetSize);
        }
コード例 #13
0
        private bool ParsePreface(ReadOnlySequence <byte> readableBuffer, out SequencePosition consumed, out SequencePosition examined)
        {
            consumed = readableBuffer.Start;
            examined = readableBuffer.End;

            if (readableBuffer.Length < ClientPreface.Length)
            {
                return(false);
            }

            var span = readableBuffer.IsSingleSegment
                ? readableBuffer.First.Span
                : readableBuffer.ToSpan();

            for (var i = 0; i < ClientPreface.Length; i++)
            {
                if (ClientPreface[i] != span[i])
                {
                    throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorInvalidPreface, Http2ErrorCode.PROTOCOL_ERROR);
                }
            }

            consumed = examined = readableBuffer.GetPosition(ClientPreface.Length);
            return(true);
        }
コード例 #14
0
    static bool TryParseLines(
        ref ReadOnlySequence <byte> buffer,
        out string message)
    {
        SequencePosition?position;
        StringBuilder    outputMessage = new();

        while (true)
        {
            position = buffer.PositionOf((byte)'\n');

            if (!position.HasValue)
            {
                break;
            }

            outputMessage.Append(Encoding.ASCII.GetString(buffer.Slice(buffer.Start, position.Value)))
            .AppendLine();

            buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
        }
        ;

        message = outputMessage.ToString();
        return(message.Length != 0);
    }
コード例 #15
0
        private static void Byte_MultiSegment_PosLong(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);
            long             sliceLen = buffer.Length;
            SequencePosition start    = buffer.GetPosition(0);

            foreach (BenchmarkIteration iteration in Benchmark.Iterations)
            {
                int localInt = 0;
                using (iteration.StartMeasurement())
                {
                    for (int i = 0; i < Benchmark.InnerIterationCount; i++)
                    {
                        ReadOnlySequence <byte> temp = buffer.Slice(start, sliceLen);
                        localInt ^= temp.Start.GetInteger();
                    }
                }
                _volatileInt = localInt;
            }
        }
コード例 #16
0
        private async Task ReadPipeAsync(PipeReader reader, CancellationToken cancellationToken = default)
        {
            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    reader.CancelPendingRead();
                    await reader.CompleteAsync();

                    break;
                }
                bool isAny = reader.TryRead(out ReadResult result);
                if (!isAny)
                {
                    continue;
                }
                ReadOnlySequence <byte> buffer = result.Buffer;
                // In the event that no message is parsed successfully, mark consumed
                // as nothing and examined as the entire buffer.
                SequencePosition consumed = buffer.Start;
                SequencePosition examined = buffer.End;
                try
                {
                    if (parser.TryParse(ref buffer, out Message message, out int bConsumed, GetName()))
                    {
                        // A single message was successfully parsed so mark the start as the
                        // parsed buffer as consumed. TryParseMessage trims the buffer to
                        // point to the data after the message was parsed.
                        consumed = buffer.GetPosition(bConsumed);

                        // Examined is marked the same as consumed here, so the next call
                        // to ReadSingleMessageAsync will process the next message if there's
                        // one.
                        examined = consumed;
                        Console.WriteLine();
                        if (!(message is null))
                        {
                            foreach (var observer in observers)
                            {
                                observer.OnNext(message);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);

                    foreach (var observer in observers)
                    {
                        observer.OnError(e);
                    }
                }
                finally
                {
                    reader.AdvanceTo(consumed, examined);
                }
            }
        }
コード例 #17
0
        public void InputUdpMessage(ref ReadOnlySequence <byte> buffer)
        {
            var udpBuffer = buffer.Slice(buffer.GetPosition(4));
            var reader    = new WrappedReader(udpBuffer, this.Order, this.readerFlushDelegate);

            this.Pipeline.OnTransportRead(this, ref reader);
            reader.Flush();
        }
コード例 #18
0
        public void GetPositionPrefersNextSegment()
        {
            BufferSegment <byte> bufferSegment1 = new BufferSegment <byte>(new byte[50]);
            BufferSegment <byte> bufferSegment2 = bufferSegment1.Append(new byte[0]);

            ReadOnlySequence <byte> buffer = new ReadOnlySequence <byte>(bufferSegment1, 0, bufferSegment2, 0);

            SequencePosition c1 = buffer.GetPosition(50);

            Assert.Equal(0, c1.GetInteger());
            Assert.Equal(bufferSegment2, c1.GetObject());

            c1 = buffer.GetPosition(50, buffer.Start);

            Assert.Equal(0, c1.GetInteger());
            Assert.Equal(bufferSegment2, c1.GetObject());
        }
コード例 #19
0
        public void SegmentStartIsConsideredInBoundsCheck()
        {
            // 0               50           100    0             50             100
            // [                ##############] -> [##############                ]
            //                         ^c1            ^c2
            var           bufferSegment1 = new BufferSegment(new byte[49]);
            BufferSegment bufferSegment2 = bufferSegment1.Append(new byte[50]);

            var buffer = new ReadOnlySequence <byte>(bufferSegment1, 0, bufferSegment2, 50);

            SequencePosition c1 = buffer.GetPosition(buffer.Start, 25); // segment 1 index 75
            SequencePosition c2 = buffer.GetPosition(buffer.Start, 55); // segment 2 index 5

            ReadOnlySequence <byte> sliced = buffer.Slice(c1, c2);

            Assert.Equal(30, sliced.Length);
        }
        public static bool TrySliceTo(this ReadOnlySequence <byte> buffer, Func <ReadOnlySequence <byte>, bool> checkFunc, out ReadOnlySequence <byte> slice, out SequencePosition position)
        {
            for (int i = 0; i < buffer.Length; ++i)
            {
                var woring = buffer.Slice(i, (buffer.Length - i));
                if (checkFunc(woring))
                {
                    slice    = buffer.Slice(0, i);
                    position = buffer.GetPosition(i);
                    return(true);
                }
            }

            slice    = buffer;
            position = buffer.GetPosition(0);
            return(false);
        }
コード例 #21
0
        private FrameReader(ref ReadOnlySequence <byte> sequence, Encoding encoding = null)
        {
            this.sequence = sequence;
            position      = sequence.GetPosition(0);

            Encoding = encoding ?? DefaultEncoding;
            Encoder  = Encoding.GetEncoder();
        }
コード例 #22
0
        internal bool TryReadOperation(ref ReadOnlySequence <byte> buffer, [MaybeNullWhen(false)] out IMemoryOwner <byte> operationResponse)
        {
            if (buffer.Length < HeaderOffsets.HeaderLength)
            {
                // Not enough data to read the body length from the header
                operationResponse = null;
                return(false);
            }

            int responseSize = HeaderOffsets.HeaderLength;
            var sizeSegment  = buffer.Slice(HeaderOffsets.BodyLength, sizeof(int));

            if (sizeSegment.IsSingleSegment)
            {
                responseSize += ByteConverter.ToInt32(sizeSegment.First.Span);
            }
            else
            {
                // Edge case, we're split across segments in the buffer
                Span <byte> tempSpan = stackalloc byte[sizeof(int)];

                sizeSegment.CopyTo(tempSpan);

                responseSize += ByteConverter.ToInt32(tempSpan);
            }

            if (buffer.Length < responseSize)
            {
                // Insufficient data, keep filling the buffer
                operationResponse = null;
                return(false);
            }

            // Slice to get operationBuffer, which is just the operation
            // And slice the original buffer to start after this operation,
            // we pass this back by ref so it's ready for the next operation

            var position        = buffer.GetPosition(responseSize);
            var operationBuffer = buffer.Slice(0, position);

            buffer = buffer.Slice(position);

            // Copy the response to a separate, contiguous memory buffer

            operationResponse = MemoryPool <byte> .Shared.RentAndSlice(responseSize);

            try
            {
                operationBuffer.CopyTo(operationResponse.Memory.Span);
                return(true);
            }
            catch
            {
                // Cleanup the memory in case of exception
                operationResponse.Dispose();
                throw;
            }
        }
コード例 #23
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="buffer">The buffer to read from.</param>
 public TokenReader(ReadOnlySequence <byte> buffer)
 {
     _buffer       = buffer;
     _spanPosition = _buffer.GetPosition(0);
     _span         = default;
     _spanIndex    = 0;
     _peek         = default;
     _hasPeeked    = false;
 }
コード例 #24
0
        public void GetOffset_SingleSegment_Slice()
        {
            ReadOnlySequence <T> buffer = new ReadOnlySequence <T>(new T[50]);

            for (int i = 0; i <= buffer.Length; i++)
            {
                Assert.Equal(buffer.Slice(0, i).Length, buffer.GetOffset(buffer.GetPosition(i)));
            }
        }
コード例 #25
0
        private static (JsonReaderState, SequencePosition, string) ProcessDataSpan(ReadOnlySequence <byte> ros, bool isFinalBlock, JsonReaderState state = default)
        {
            var builder = new StringBuilder();
            ReadOnlySpan <byte> leftOver = default;

            byte[]         pooledArray   = null;
            JsonUtf8Reader json          = default;
            long           totalConsumed = 0;

            foreach (ReadOnlyMemory <byte> mem in ros)
            {
                ReadOnlySpan <byte> span = mem.Span;

                if (leftOver.Length > int.MaxValue - span.Length)
                {
                    throw new ArgumentOutOfRangeException("Current sequence segment size is too large to fit left over data from the previous segment into a 2 GB buffer.");
                }

                pooledArray = ArrayPool <byte> .Shared.Rent(span.Length + leftOver.Length);    // This is guaranteed to not overflow

                Span <byte> bufferSpan = pooledArray.AsSpan(0, leftOver.Length + span.Length);
                leftOver.CopyTo(bufferSpan);
                span.CopyTo(bufferSpan.Slice(leftOver.Length));

                json = new JsonUtf8Reader(bufferSpan, isFinalBlock, state);

                while (json.Read())
                {
                    switch (json.TokenType)
                    {
                    case JsonTokenType.PropertyName:
                        json.TryGetValueAsString(out string value);
                        builder.Append(value);
                        break;
                    }
                }

                if (json.BytesConsumed < bufferSpan.Length)
                {
                    leftOver = bufferSpan.Slice((int)json.BytesConsumed);
                }
                else
                {
                    leftOver = default;
                }
                totalConsumed += json.BytesConsumed;
                Assert.Equal(json.BytesConsumed, json.CurrentState.BytesConsumed);
                Assert.Equal(json.Position, json.CurrentState.Position);
                if (pooledArray != null)    // TODO: Will this work if data spans more than two segments?
                {
                    ArrayPool <byte> .Shared.Return(pooledArray);
                }

                state = json.CurrentState;
            }
            return(json.CurrentState, ros.GetPosition(totalConsumed), builder.ToString());
        }
コード例 #26
0
        private FrameReader Reset(ref ReadOnlySequence <byte> value)
        {
            sequence = value;
            position = sequence.GetPosition(0);

            Encoder.Reset();

            return(this);
        }
コード例 #27
0
        // Adapted from https://devblogs.microsoft.com/dotnet/system-io-pipelines-high-performance-io-in-net/
        public static async Task ReadLinesUsingPipesAsync(this Stream stream, Func <ReadOnlySequence <byte>, Task> callback, CancellationToken token = default, char separator = '\n')
        {
            var pipe = new Pipe();

            try
            {
                await StressTaskExtensions.WhenAllThrowOnFirstException(token, FillPipeAsync, ReadPipeAsync);
            }
            catch (OperationCanceledException) when(token.IsCancellationRequested)
            {
            }

            async Task FillPipeAsync(CancellationToken token)
            {
                try
                {
                    await stream.CopyToAsync(pipe.Writer, token);
                }
                catch (Exception e)
                {
                    pipe.Writer.Complete(e);
                    throw;
                }

                pipe.Writer.Complete();
            }

            async Task ReadPipeAsync(CancellationToken token)
            {
                while (!token.IsCancellationRequested)
                {
                    ReadResult result = await pipe.Reader.ReadAsync(token);

                    ReadOnlySequence <byte> buffer = result.Buffer;
                    SequencePosition?       position;

                    do
                    {
                        position = buffer.PositionOf((byte)separator);

                        if (position != null)
                        {
                            await callback(buffer.Slice(0, position.Value));

                            buffer = buffer.Slice(buffer.GetPosition(1, position.Value));
                        }
                    }while (position != null);

                    pipe.Reader.AdvanceTo(buffer.Start, buffer.End);

                    if (result.IsCompleted)
                    {
                        break;
                    }
                }
            }
        }
コード例 #28
0
        public void GetPositionDoesNotCrossOutsideBuffer()
        {
            var bufferSegment1 = new BufferSegment <byte>(new byte[100]);
            BufferSegment <byte> bufferSegment2 = bufferSegment1.Append(new byte[100]);
            BufferSegment <byte> bufferSegment3 = bufferSegment2.Append(new byte[0]);

            var buffer = new ReadOnlySequence <byte>(bufferSegment1, 0, bufferSegment2, 100);

            SequencePosition c1 = buffer.GetPosition(200);

            Assert.Equal(100, c1.GetInteger());
            Assert.Equal(bufferSegment2, c1.GetObject());

            c1 = buffer.GetPosition(200, buffer.Start);

            Assert.Equal(100, c1.GetInteger());
            Assert.Equal(bufferSegment2, c1.GetObject());
        }
コード例 #29
0
        public void GetOffset_MultiSegment_Slice()
        {
            ReadOnlySequence <T> buffer = GetFourSegmentsReadOnlySequence();

            for (int i = 0; i <= buffer.Length; i++)
            {
                Assert.Equal(buffer.Slice(0, i).Length, buffer.GetOffset(buffer.GetPosition(i)));
            }
        }
コード例 #30
0
        public void SeekSkipsEmptySegments()
        {
            var bufferSegment1 = new BufferSegment <T>(new T[100]);
            BufferSegment <T> bufferSegment2 = bufferSegment1.Append(new T[0]);
            BufferSegment <T> bufferSegment3 = bufferSegment2.Append(new T[0]);
            BufferSegment <T> bufferSegment4 = bufferSegment3.Append(new T[100]);

            var buffer = new ReadOnlySequence <T>(bufferSegment1, 0, bufferSegment4, 100);

            SequencePosition c1 = buffer.GetPosition(100);

            Assert.Equal(0, c1.GetInteger());
            Assert.Equal(bufferSegment4, c1.GetObject());

            c1 = buffer.GetPosition(100, buffer.Start);

            Assert.Equal(0, c1.GetInteger());
            Assert.Equal(bufferSegment4, c1.GetObject());
        }