DotNext by .NET Foundation and Contributors

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

.NET API 495,000 bytes

 BufferWriterSlim<T>

public struct BufferWriterSlim<T>
Represents stack-allocated buffer writer.
using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Buffers { [StructLayout(LayoutKind.Auto)] [NullableContext(1)] [Nullable(0)] [CompilerFeatureRequired("RefStructs")] [DebuggerDisplay("WrittenCount = {WrittenCount}, FreeCapacity = {FreeCapacity}, Overflow = {Overflow}")] public ref struct BufferWriterSlim<[Nullable(2)] T> { [StructLayout(LayoutKind.Auto)] [CompilerFeatureRequired("RefStructs")] internal readonly ref struct Ref { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ref byte reference; [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal unsafe ref BufferWriterSlim<T> Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref Ref.<get_Value>g__AsWriter|3_0(*(ref byte*)(&reference)); } } internal unsafe Ref(ref BufferWriterSlim<T> writer) { *(ref byte*)(&reference) = ref <.ctor>g__AsRef|1_0(ref writer); } } private readonly Span<T> initialBuffer; private readonly MemoryAllocator<T> allocator; private MemoryOwner<T> extraBuffer; private int position; [DebuggerBrowsable(DebuggerBrowsableState.Never)] [ExcludeFromCodeCoverage] private int Overflow { [IsReadOnly] get { return Math.Max(0, position - initialBuffer.Length); } } public int WrittenCount { [IsReadOnly] get { return position; } set { ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)value, (uint)Capacity, "value"); position = value; } } public int Capacity { [IsReadOnly] get { if (!extraBuffer.IsEmpty) return extraBuffer.Length; return initialBuffer.Length; } } public int FreeCapacity { [IsReadOnly] get { return Capacity - WrittenCount; } } private bool NoOverflow { [IsReadOnly] get { return position <= initialBuffer.Length; } } [Nullable(new byte[] { 0, 1 })] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private Span<T> Buffer { [IsReadOnly] get { if (!NoOverflow) return extraBuffer.Span; return initialBuffer; } } [Nullable(new byte[] { 0, 1 })] public ReadOnlySpan<T> WrittenSpan { [IsReadOnly] [return: Nullable(new byte[] { 0, 1 })] get { return Buffer.Slice(0, position); } } public ref T this[int index] { [IsReadOnly] get { ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, (uint)position, "index"); return ref Unsafe.Add<T>(ref MemoryMarshal.GetReference<T>(Buffer), index); } } public BufferWriterSlim([Nullable(new byte[] { 0, 1 })] Span<T> buffer, [Nullable(new byte[] { 2, 1 })] MemoryAllocator<T> allocator = null) { extraBuffer = default(MemoryOwner<T>); position = 0; initialBuffer = buffer; this.allocator = allocator; } public BufferWriterSlim(int initialCapacity, [Nullable(new byte[] { 2, 1 })] MemoryAllocator<T> allocator = null) { initialBuffer = default(Span<T>); position = 0; ArgumentOutOfRangeException.ThrowIfNegative<int>(initialCapacity, "initialCapacity"); this.allocator = allocator; extraBuffer = ((initialCapacity == 0) ? default(MemoryOwner<T>) : Memory.AllocateAtLeast<T>(allocator, initialCapacity)); } [return: Nullable(new byte[] { 0, 1 })] public Span<T> GetSpan(int sizeHint = 0) { ArgumentOutOfRangeException.ThrowIfNegative<int>(sizeHint, "sizeHint"); return InternalGetSpan(sizeHint); } internal Span<T> InternalGetSpan(int sizeHint) { int newSize; Span<T> span; if (extraBuffer.IsEmpty) { int length = initialBuffer.Length; int writtenCount = position; if (((IGrowableBuffer<T>)).GetBufferSize(sizeHint, length, writtenCount, out newSize)) { extraBuffer = Memory.AllocateAtLeast<T>(allocator, newSize); initialBuffer.CopyTo(span = extraBuffer.Span); } else span = initialBuffer; } else { int length2 = extraBuffer.Length; int writtenCount2 = position; if (((IGrowableBuffer<T>)).GetBufferSize(sizeHint, length2, writtenCount2, out newSize)) Memory.Resize<T>(ref extraBuffer, newSize, allocator); span = extraBuffer.Span; } return span.Slice(position); } public void Advance(int count) { ArgumentOutOfRangeException.ThrowIfNegative<int>(count, "count"); int num = position + count; if (num > Capacity) <Advance>g__ThrowInvalidOperationException|24_0(); position = num; } public void Rewind(int count) { ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)count, (uint)position, "count"); if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) { Span<T> span = Buffer; span = span.Slice(count); span.Clear(); } position -= count; } public void Write([ScopedRef] [Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> input) { if (!input.IsEmpty) { input.CopyTo(InternalGetSpan(input.Length)); position += input.Length; } } public void Add(T item) { Add() = item; } public ref T Add() { ref T reference = ref MemoryMarshal.GetReference<T>(InternalGetSpan(1)); position++; return ref reference; } [IsReadOnly] [NullableContext(2)] public bool TryPeek([MaybeNullWhen(false)] out T item) { if (position > 0) { item = Unsafe.Add<T>(ref MemoryMarshal.GetReference<T>(Buffer), position - 1); return true; } item = default(T); return false; } [NullableContext(2)] public bool TryPop([MaybeNullWhen(false)] out T item) { if (position > 0) { item = Unsafe.Add<T>(ref MemoryMarshal.GetReference<T>(Buffer), --position); return true; } item = default(T); return false; } public bool TryPop([ScopedRef] [Nullable(new byte[] { 0, 1 })] Span<T> output) { if (position >= output.Length) { Span<T> span = Buffer; span = span.Slice(position - output.Length, output.Length); if (span.TryCopyTo(output)) { position -= output.Length; return true; } } return false; } public bool TryDetachBuffer([Nullable(new byte[] { 0, 1 })] out MemoryOwner<T> owner) { if (NoOverflow) { owner = default(MemoryOwner<T>); return false; } owner = extraBuffer; owner.Truncate(position); position = 0; extraBuffer = default(MemoryOwner<T>); return true; } public void Clear(bool reuseBuffer = false) { initialBuffer.Clear(); if (!reuseBuffer) extraBuffer.Dispose(); else if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) { extraBuffer.Span.Clear(); } position = 0; } public void Dispose() { if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) { initialBuffer.Clear(); extraBuffer.Clear(true); } else extraBuffer.Clear(false); this = default(BufferWriterSlim<T>); } [IsReadOnly] public override string ToString() { return WrittenSpan.ToString(); } } }