public void Dispose()
        {
            // TODO: put object disposed guards in front of operations
            var segment = _firstSegment;

            _firstSegment = null;
            _lastSegment  = null;
            while (segment != null)
            {
                var nextSegment = segment.Next;
                segment.Dispose();
                segment = nextSegment;
            }
        }
        public Memory <byte> GetTrailingMemory(int sizeHint = 0)
        {
            // special case, no buffers.
            // allocate buffer on first read.
            if (_firstSegment == null && _lastSegment == null)
            {
                var rental  = _memoryPool.Rent(sizeHint);
                var segment = new RollingMemorySegment(rental, 0);
                _firstSegment = segment;
                _lastSegment  = segment;
                return(rental.Memory);
            }

            // special case, all occupied memory has been consumed.
            // drop both index to 0 so the entire page becomes trailing memory again.
            if (IsEmpty)
            {
                _firstIndex = 0;
                _lastIndex  = 0;
            }

            // special case, last page does not have enough memory to hold sizeHint
            if (_lastIndex + sizeHint > _lastSegment.Memory.Length)
            {
                _lastSegment.Shrink(_lastIndex);
            }

            // special case, last page is completely full.
            // allocate and append a new unoccupied last page.
            if (_lastIndex == _lastSegment.Memory.Length)
            {
                var rental = _memoryPool.Rent(sizeHint);
                _lastSegment.Next = new RollingMemorySegment(
                    rental,
                    _lastSegment.RunningIndex + _lastIndex);
                _lastSegment = _lastSegment.Next;
                _lastIndex   = 0;
                return(rental.Memory);
            }

            return(MemoryMarshal.AsMemory(_lastSegment.Memory.Slice(_lastIndex)));
        }
        public void DisposeFirstSegment()
        {
            if (_firstSegment == null && _lastSegment == null)
            {
                return;
            }

            var disposedSegment = _firstSegment;

            if (_firstSegment == _lastSegment)
            {
                _firstSegment = null;
                _firstIndex   = 0;
                _lastSegment  = null;
                _lastIndex    = 0;
            }
            else
            {
                _firstSegment = disposedSegment.Next;
                _firstIndex   = 0;
            }

            disposedSegment.Dispose();
        }