DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.0.0-beta.3" />

 PooledBufferWriter<T>

public sealed class PooledBufferWriter<T> : BufferWriter<T>, IMemoryOwner<T>, IDisposable
Represents memory writer that uses pooled memory.
using System; using System.Buffers; using System.Runtime.CompilerServices; namespace DotNext.Buffers { [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public sealed class PooledBufferWriter<[System.Runtime.CompilerServices.Nullable(2)] T> : BufferWriter<T>, IMemoryOwner<T>, IDisposable { [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] private readonly MemoryAllocator<T> allocator; [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private MemoryOwner<T> buffer; public override int Capacity { get { ThrowIfDisposed(); return buffer.Length; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public override ReadOnlyMemory<T> WrittenMemory { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] get { return GetWrittenMemory(); } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] Memory<T> IMemoryOwner<T>.Memory { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] get { return GetWrittenMemory(); } } public PooledBufferWriter([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] MemoryAllocator<T> allocator, int initialCapacity) { if (initialCapacity <= 0) throw new ArgumentOutOfRangeException("initialCapacity"); this.allocator = allocator; buffer = MemoryAllocator.Invoke<T>(allocator, initialCapacity, false); } public PooledBufferWriter([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] MemoryAllocator<T> allocator = null) { this.allocator = allocator; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] private Memory<T> GetWrittenMemory() { ThrowIfDisposed(); return buffer.Memory.Slice(0, position); } public override void Clear(bool reuseBuffer) { ThrowIfDisposed(); if (!reuseBuffer) buffer.Dispose(); else if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) { buffer.Memory.Span.Clear(); } position = 0; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public override Memory<T> GetMemory(int sizeHint = 0) { CheckAndResizeBuffer(sizeHint); return buffer.Memory.Slice(position); } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public override MemoryOwner<T> DetachBuffer() { ThrowIfDisposed(); MemoryOwner<T> result; if (position > 0) { result = buffer; buffer = default(MemoryOwner<T>); result.Truncate(position); position = 0; } else result = default(MemoryOwner<T>); return result; } private protected override void Resize(int newSize) { BufferHelpers.Resize<T>(ref buffer, newSize, false, allocator); base.AllocationCounter?.WriteMetric((float)buffer.Length); } protected override void Dispose(bool disposing) { if (disposing) { base.BufferSizeCallback?.Invoke(buffer.Length); buffer.Dispose(); } base.Dispose(disposing); } } }