DotNext by Roman Sakno

<PackageReference Include="DotNext" Version="3.1.1" />

 BufferWriter<T>

Represents memory-backed output sink which T data can be written.
using DotNext.Collections.Generic; using System; using System.Buffers; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace DotNext.Buffers { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] [DebuggerDisplay("WrittenCount = {WrittenCount}, FreeCapacity = {FreeCapacity}")] public abstract class BufferWriter<[System.Runtime.CompilerServices.Nullable(2)] T> : Disposable, IBufferWriter<T>, ISupplier<ReadOnlyMemory<T>>, IReadOnlyList<T>, IEnumerable<T>, IEnumerable, IReadOnlyCollection<T>, IGrowableBuffer<T>, IReadOnlySpanConsumer<T>, ISupplier<ReadOnlyMemory<T>, CancellationToken, ValueTask>, IDisposable { [System.Runtime.CompilerServices.Nullable(2)] private object diagObj; private protected int position; [System.Runtime.CompilerServices.Nullable(2)] public EventCounter AllocationCounter { [System.Runtime.CompilerServices.NullableContext(2)] private protected get { return diagObj as EventCounter; } [System.Runtime.CompilerServices.NullableContext(2)] [param: DisallowNull] set { diagObj = value; } } [System.Runtime.CompilerServices.Nullable(2)] public Action<int> BufferSizeCallback { [System.Runtime.CompilerServices.NullableContext(2)] private protected get { return diagObj as Action<int>; } [System.Runtime.CompilerServices.NullableContext(2)] [param: DisallowNull] set { diagObj = value; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public abstract ReadOnlyMemory<T> WrittenMemory { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] get; } public int WrittenCount { get { ThrowIfDisposed(); return position; } } long IGrowableBuffer<T>.WrittenCount { get { return WrittenCount; } } int IReadOnlyCollection<T>.Count { get { return WrittenCount; } } [IsReadOnly] public ref T this[int index] { [return: IsReadOnly] get { return ref WrittenMemory.Span[index]; } } T IReadOnlyList<T>.this[int index] { get { return this[index]; } } public abstract int Capacity { get; } public int FreeCapacity { get { ThrowIfDisposed(); return Capacity - WrittenCount; } } private protected BufferWriter() { } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlyMemory<T> ISupplier<ReadOnlyMemory<T>>.Invoke() { return WrittenMemory; } void IGrowableBuffer<T>.Write([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> input) { BuffersExtensions.Write<T>((IBufferWriter<T>)this, input); } void IGrowableBuffer<T>.CopyTo<TConsumer>(TConsumer consumer) { ((IReadOnlySpanConsumer<T>)consumer).Invoke(this.WrittenMemory.Span); } void IGrowableBuffer<T>.Clear() { Clear(false); } int IGrowableBuffer<T>.CopyTo([System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] Span<T> output) { Span.CopyTo<T>(WrittenMemory.Span, output, out int writtenCount); return writtenCount; } ValueTask IGrowableBuffer<T>.CopyToAsync<TConsumer>(TConsumer consumer, CancellationToken token) { if (!base.IsDisposed) return ((ISupplier<ReadOnlyMemory<T>, CancellationToken, ValueTask>)consumer).Invoke(this.WrittenMemory, token); return new ValueTask(base.DisposedTask); } public void Add(T item) { GetSpan(1)[0] = item; Advance(1); } public void AddAll(ICollection<T> items) { if (items.Count != 0) { Span<T> span = GetSpan(items.Count); int i = default(int); using (IEnumerator<T> enumerator = items.GetEnumerator()) { for (i = 0; i < items.Count; i++) { if (!enumerator.MoveNext()) break; span[i] = enumerator.Current; } } Advance(i); } } public abstract void Clear(bool reuseBuffer = false); public void Advance(int count) { ThrowIfDisposed(); if (count < 0) throw new ArgumentOutOfRangeException("count"); if (position > Capacity - count) throw new InvalidOperationException(); position += count; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public abstract Memory<T> GetMemory(int sizeHint = 0); [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public virtual Span<T> GetSpan(int sizeHint = 0) { return GetMemory(sizeHint).Span; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public abstract MemoryOwner<T> DetachBuffer(); private protected abstract void Resize(int newSize); private protected void CheckAndResizeBuffer(int sizeHint) { int capacity = Capacity; int writtenCount = position; int? bufferSize = ((IGrowableBuffer<T>)).GetBufferSize(sizeHint, capacity, writtenCount); if (bufferSize.HasValue) Resize(bufferSize.GetValueOrDefault()); } protected override void Dispose(bool disposing) { if (disposing) diagObj = null; base.Dispose(disposing); } public IEnumerator<T> GetEnumerator() { return Sequence.ToEnumerator<T>(WrittenMemory); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public override string ToString() { return WrittenMemory.ToString(); } } }