/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. *--------------------------------------------------------------------------------------------*/ namespace System.Buffers; internal sealed class ArrayBufferWriter : IBufferWriter { private const int DefaultInitialBufferSize = 256; private T[] _buffer; private int _index; public ArrayBufferWriter() : this(DefaultInitialBufferSize) { } public ArrayBufferWriter(int initialCapacity) { if (initialCapacity < 0) { throw new ArgumentOutOfRangeException(nameof(initialCapacity)); } _buffer = initialCapacity == 0 ? [] : new T[initialCapacity]; } public ReadOnlyMemory WrittenMemory => _buffer.AsMemory(0, _index); public ReadOnlySpan WrittenSpan => _buffer.AsSpan(0, _index); public int WrittenCount => _index; public int Capacity => _buffer.Length; public int FreeCapacity => _buffer.Length - _index; public void Clear() { _buffer.AsSpan(0, _index).Clear(); _index = 0; } public void Advance(int count) { if (count < 0) { throw new ArgumentOutOfRangeException(nameof(count)); } if (count > FreeCapacity) { throw new InvalidOperationException("Cannot advance past the end of the buffer."); } _index += count; } public Memory GetMemory(int sizeHint = 0) { CheckAndResizeBuffer(sizeHint); return _buffer.AsMemory(_index); } public Span GetSpan(int sizeHint = 0) { CheckAndResizeBuffer(sizeHint); return _buffer.AsSpan(_index); } private void CheckAndResizeBuffer(int sizeHint) { if (sizeHint < 0) { throw new ArgumentOutOfRangeException(nameof(sizeHint)); } if (sizeHint == 0) { sizeHint = 1; } if (sizeHint <= FreeCapacity) { return; } var growBy = Math.Max(sizeHint, _buffer.Length); var newSize = checked(_buffer.Length + growBy); Array.Resize(ref _buffer, newSize); } }