/// <summary>
        /// Reads the current token, ensuring enough data is pulled from the underlying reader
        /// </summary>
        /// <param name="reader">A reference to the UTF-8 JSON Reader used to read JSON</param>
        public void Read(ref Utf8JsonReader reader)
        {
            while (!reader.Read())
            {
                // Insufficient data in the buffer for this token, pull more from the Reader
                var Consumed = (int)reader.BytesConsumed;

                if (Consumed > 0)
                {
                    var RemovedLength = 0;

                    // Trim what leftover data we can
                    if (_LeftoverHead != null)
                    {
                        // Remove segments and decrease Consumed until we run out of segments, or run out of Consumed bytes
                        while (_LeftoverHead.Memory.Length < Consumed)
                        {
                            var OldLength = _LeftoverHead.Memory.Length;

                            Consumed      -= OldLength;
                            RemovedLength += OldLength;

                            if (MemoryMarshal.TryGetArray(_LeftoverHead.Memory, out var LeftoverBuffer))
                            {
                                ArrayPool <byte> .Shared.Return(LeftoverBuffer.Array !);
                            }

                            if (_HasExtraTail && _LeftoverHead == _LeftoverTail)
                            {
                                _LeftoverHead = null;
                            }
                            else
                            {
                                _LeftoverHead = (LeftoverSegment?)_LeftoverHead.Next;
                            }

                            if (_LeftoverHead == null)
                            {
                                break;
                            }
                        }

                        var NextSegment = _LeftoverHead;

                        if (NextSegment != null)
                        {
                            // Correct the remainder on the header
                            NextSegment.CorrectMemory(Consumed);
                            NextSegment.CorrectRunningIndex(RemovedLength);
                            NextSegment = (LeftoverSegment?)NextSegment.Next;

                            // Correct the Running Index on subsequent entries
                            while (NextSegment != null)
                            {
                                NextSegment.CorrectRunningIndex(Consumed + RemovedLength);

                                if (_HasExtraTail && NextSegment == _LeftoverTail)
                                {
                                    NextSegment = null;
                                }
                                else
                                {
                                    NextSegment = (LeftoverSegment?)NextSegment.Next;
                                }
                            }

                            Consumed = 0;
                        }
                        else
                        {
                            // We removed all saved segments, leaving only the contents of the current buffer
                            _LeftoverTail = null;
                            _HasExtraTail = false;
                        }
                    }
                }

                // Have we consumed all of the supplied buffer?
                if (Consumed == _LastBuffer.Length)
                {
                    // No need to pass anything on to the next reader
                    _Reader.Advance(_LastBuffer.Length);

                    _LastBuffer   = _Reader.GetMemory(0);
                    _HasExtraTail = false;

                    // If this is the final block, this will probably fail on the next read, since the consumer called Read after the final token
                    reader = new Utf8JsonReader(_LastBuffer.Span, _LastBuffer.IsEmpty, reader.CurrentState);
                }
                else
                {
                    // Before we advance, capture anything leftover and record a segment
                    var Remainder = _LastBuffer.Length - Consumed;

                    var Buffer = ArrayPool <byte> .Shared.Rent(Remainder);

                    _LastBuffer.Slice(Consumed).CopyTo(Buffer);

                    if (_LeftoverTail == null)
                    {
                        // No start segment, so create it
                        _LeftoverTail = _LeftoverHead = new LeftoverSegment(Buffer.AsMemory(0, Remainder));
                    }
                    else
                    {
                        // We have an existing head segment, chain a new segment to it
                        _LeftoverTail = new LeftoverSegment(_LeftoverTail, Buffer.AsMemory(0, Remainder));
                    }

                    // Now it's safe to advance and grab the next buffer
                    _Reader.Advance(Consumed);

                    _LastBuffer = _Reader.GetMemory(0);

                    if (_LastBuffer.IsEmpty)
                    {
                        // No more data, finalise the reader
                        reader = new Utf8JsonReader(new ReadOnlySequence <byte>(_LeftoverHead !, 0, _LeftoverTail, _LeftoverTail.Memory.Length), true, reader.CurrentState);

                        _HasExtraTail = false;

                        // The next read (when we hit the end of the while and loop back) will throw if the JSON is truncated
                    }
                    else
                    {
                        // More data, continue the reader
                        // Create a temp segment representing any previous data, along with our new buffer
                        var TempSegment = new LeftoverSegment(_LeftoverTail, _LastBuffer);

                        _HasExtraTail = true;

                        reader = new Utf8JsonReader(new ReadOnlySequence <byte>(_LeftoverHead !, 0, TempSegment, TempSegment.Memory.Length), false, reader.CurrentState);
                    }
                }
            }
        }
 internal LeftoverSegment(LeftoverSegment previous, ReadOnlyMemory <byte> memory)
 {
     Memory        = memory;
     RunningIndex  = previous.RunningIndex + previous.Memory.Length;
     previous.Next = this;
 }