ArrayBufferWriter<T>
namespace System.Buffers
{
    internal sealed class ArrayBufferWriter<T> : IBufferWriter<T>
    {
        private const int ArrayMaxLength = 2147483591;
        private const int DefaultInitialBufferSize = 256;
        private T[] _buffer;
        private int _index;
        public ReadOnlyMemory<T> WrittenMemory => MemoryExtensions.AsMemory<T>(_buffer, 0, _index);
        public ReadOnlySpan<T> WrittenSpan => MemoryExtensions.AsSpan<T>(_buffer, 0, _index);
        public int WrittenCount => _index;
        public int Capacity => _buffer.Length;
        public int FreeCapacity => _buffer.Length - _index;
        public ArrayBufferWriter()
        {
            _buffer = Array.Empty<T>();
            _index = 0;
        }
        public ArrayBufferWriter(int initialCapacity)
        {
            if (initialCapacity <= 0)
                throw new ArgumentException(null, "initialCapacity");
            _buffer = new T[initialCapacity];
            _index = 0;
        }
        public void Clear()
        {
            MemoryExtensions.AsSpan<T>(_buffer, 0, _index).Clear();
            _index = 0;
        }
        public void ResetWrittenCount()
        {
            _index = 0;
        }
        public void Advance(int count)
        {
            if (count < 0)
                throw new ArgumentException(null, "count");
            if (_index > _buffer.Length - count)
                ThrowInvalidOperationException_AdvancedTooFar(_buffer.Length);
            _index += count;
        }
        public Memory<T> GetMemory(int sizeHint = 0)
        {
            CheckAndResizeBuffer(sizeHint);
            return MemoryExtensions.AsMemory<T>(_buffer, _index);
        }
        public Span<T> GetSpan(int sizeHint = 0)
        {
            CheckAndResizeBuffer(sizeHint);
            return MemoryExtensions.AsSpan<T>(_buffer, _index);
        }
        private void CheckAndResizeBuffer(int sizeHint)
        {
            if (sizeHint < 0)
                throw new ArgumentException("sizeHint");
            if (sizeHint == 0)
                sizeHint = 1;
            if (sizeHint > FreeCapacity) {
                int num = _buffer.Length;
                int num2 = Math.Max(sizeHint, num);
                if (num == 0)
                    num2 = Math.Max(num2, 256);
                int num3 = num + num2;
                if ((uint)num3 > 2147483647) {
                    uint num4 = (uint)(num - FreeCapacity + sizeHint);
                    if (num4 > 2147483591)
                        ThrowOutOfMemoryException(num4);
                    num3 = 2147483591;
                }
                Array.Resize<T>(ref _buffer, num3);
            }
        }
        private static void ThrowInvalidOperationException_AdvancedTooFar(int capacity)
        {
            throw new InvalidOperationException(System.SR.Format(System.SR.BufferWriterAdvancedTooFar, capacity));
        }
        private static void ThrowOutOfMemoryException(uint capacity)
        {
            throw new OutOfMemoryException(System.SR.Format(System.SR.BufferMaximumSizeExceeded, capacity));
        }
    }
}