PooledArrayBufferWriter<T>
public sealed class PooledArrayBufferWriter<T> : BufferWriter<T>, ISupplier<ArraySegment<T>>, IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable
Represents memory writer that is backed by the array obtained from the pool.
using DotNext.Runtime;
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public sealed class PooledArrayBufferWriter<[System.Runtime.CompilerServices.Nullable(2)] T> : BufferWriter<T>, ISupplier<ArraySegment<T>>, IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable
{
private readonly ArrayPool<T> pool;
private T[] buffer;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})]
public ArrayPool<T> BufferPool {
[param: System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})]
set {
if (value == null)
value = ArrayPool<T>.Shared;
int num = buffer.Length;
if (num > 0) {
pool.Return(buffer, false);
buffer = value.Rent(num);
}
pool = value;
}
}
int ICollection<T>.Count {
get {
return base.WrittenCount;
}
}
bool ICollection<T>.IsReadOnly {
get {
return false;
}
}
public new ref T this[int index] {
get {
return ref this[(long)index];
}
}
public unsafe ref T this[long index] {
get {
ThrowIfDisposed();
if ((ulong)index >= (ulong)position)
throw new ArgumentOutOfRangeException("index");
return ref Unsafe.Add<T>(ref MemoryMarshal.GetArrayDataReference<T>(buffer), (IntPtr)(void*)index);
}
}
T IList<T>.this[int index] {
get {
return this[index];
}
set {
this[index] = value;
}
}
public override int Capacity {
get {
ThrowIfDisposed();
return buffer.Length;
}
set {
if (value < 0)
throw new ArgumentOutOfRangeException("value");
if (value > 0)
buffer = pool.Rent(value);
}
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public override ReadOnlyMemory<T> WrittenMemory {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
get {
ThrowIfDisposed();
return new Memory<T>(buffer, 0, position);
}
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public ArraySegment<T> WrittenArray {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
get {
ThrowIfDisposed();
return new ArraySegment<T>(buffer, 0, position);
}
}
[Obsolete("Use init-only properties to set the capacity and allocator")]
public PooledArrayBufferWriter(ArrayPool<T> pool, int initialCapacity)
{
if (initialCapacity <= 0)
throw new ArgumentOutOfRangeException("initialCapacity");
this.pool = pool;
buffer = pool.Rent(initialCapacity);
}
[Obsolete("Use init-only properties to set the capacity and pool")]
public PooledArrayBufferWriter(ArrayPool<T> pool)
{
this.pool = pool;
buffer = Array.Empty<T>();
}
[Obsolete("Use init-only properties to set the capacity and pool")]
public PooledArrayBufferWriter(int initialCapacity)
: this(ArrayPool<T>.Shared, initialCapacity)
{
}
public PooledArrayBufferWriter()
{
pool = ArrayPool<T>.Shared;
buffer = Array.Empty<T>();
}
void ICollection<T>.CopyTo(T[] array, int arrayIndex)
{
WrittenMemory.CopyTo(MemoryExtensions.AsMemory<T>(array, arrayIndex));
}
int IList<T>.IndexOf(T item)
{
ThrowIfDisposed();
return Array.IndexOf<T>(buffer, item, 0, position);
}
bool ICollection<T>.Contains(T item)
{
ThrowIfDisposed();
return Array.IndexOf<T>(buffer, item, 0, position) >= 0;
}
private void RemoveAt(int index)
{
Array.Copy(buffer, (long)index + 1, buffer, index, (long)(position - index) - 1);
buffer[position - 1] = default(T);
if (--position == 0) {
ReleaseBuffer();
buffer = Array.Empty<T>();
}
}
void IList<T>.RemoveAt(int index)
{
ThrowIfDisposed();
if ((uint)index >= (uint)position)
throw new ArgumentOutOfRangeException("index");
RemoveAt(index);
}
bool ICollection<T>.Remove(T item)
{
ThrowIfDisposed();
int num = Array.IndexOf<T>(buffer, item, 0, position);
if (num < 0)
return false;
RemoveAt(num);
return true;
}
void IList<T>.Insert(int index, T item)
{
Insert(index, MemoryMarshal.CreateReadOnlySpan<T>(ref item, 1));
}
public void Insert(int index, [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> items)
{
ThrowIfDisposed();
if ((uint)index > (uint)position)
throw new ArgumentOutOfRangeException("index");
if (!items.IsEmpty) {
if (Intrinsics.GetLength(buffer) == (IntPtr)0)
buffer = pool.Rent(items.Length);
else if ((long)(position + items.Length) <= (long)Intrinsics.GetLength(buffer)) {
Array.Copy(buffer, index, buffer, index + items.Length, position - index);
} else {
T[] destinationArray = pool.Rent(buffer.Length + items.Length);
Array.Copy(buffer, 0, destinationArray, 0, index);
Array.Copy(buffer, index, destinationArray, index + items.Length, buffer.LongLength - index);
ReleaseBuffer();
buffer = destinationArray;
}
items.CopyTo(MemoryExtensions.AsSpan<T>(buffer, index));
position += items.Length;
}
}
public void Overwrite(int index, [System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> items)
{
ThrowIfDisposed();
if ((uint)index > (uint)position)
throw new ArgumentOutOfRangeException("index");
if (Intrinsics.GetLength(buffer) == (IntPtr)0)
buffer = pool.Rent(items.Length);
else if ((long)(index + items.Length) <= (long)Intrinsics.GetLength(buffer)) {
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
Array.Clear(buffer, index, position - index);
} else {
T[] destinationArray = pool.Rent(index + items.Length);
Array.Copy(buffer, 0, destinationArray, 0, index);
ReleaseBuffer();
buffer = destinationArray;
}
items.CopyTo(MemoryExtensions.AsSpan<T>(buffer, index));
position = index + items.Length;
}
void ICollection<T>.Clear()
{
Clear(false);
}
ArraySegment<T> ISupplier<ArraySegment<T>>.Invoke()
{
return WrittenArray;
}
private void ReleaseBuffer()
{
if ((long)Intrinsics.GetLength(buffer) > 0)
pool.Return(buffer, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
}
public override void Clear(bool reuseBuffer = false)
{
ThrowIfDisposed();
if (!reuseBuffer) {
ReleaseBuffer();
buffer = Array.Empty<T>();
} else if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) {
Array.Clear(buffer, 0, position);
}
position = 0;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public override MemoryOwner<T> DetachBuffer()
{
ThrowIfDisposed();
MemoryOwner<T> result;
if (position > 0) {
result = new MemoryOwner<T>(pool, buffer, position);
buffer = Array.Empty<T>();
position = 0;
} else
result = default(MemoryOwner<T>);
return result;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public override Memory<T> GetMemory(int sizeHint = 0)
{
if (sizeHint < 0)
throw new ArgumentOutOfRangeException("sizeHint");
CheckAndResizeBuffer(sizeHint);
return MemoryExtensions.AsMemory<T>(buffer, position);
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public override Span<T> GetSpan(int sizeHint = 0)
{
if (sizeHint < 0)
throw new ArgumentOutOfRangeException("sizeHint");
CheckAndResizeBuffer(sizeHint);
return MemoryExtensions.AsSpan<T>(buffer, position);
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public ArraySegment<T> GetArray(int sizeHint = 0)
{
if (sizeHint < 0)
throw new ArgumentOutOfRangeException("sizeHint");
CheckAndResizeBuffer(sizeHint);
return new ArraySegment<T>(buffer, position, buffer.Length - position);
}
public override void AddAll(ICollection<T> items)
{
ThrowIfDisposed();
int count = items.Count;
if (count > 0) {
CheckAndResizeBuffer(count);
items.CopyTo(buffer, position);
position += count;
}
}
public void RemoveLast(int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException("count");
ThrowIfDisposed();
if (count >= position) {
ReleaseBuffer();
buffer = Array.Empty<T>();
position = 0;
} else if (count > 0) {
int num = position - count;
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
Array.Clear(buffer, num, position - num);
position = num;
}
}
public void RemoveFirst(int count)
{
if (count < 0)
throw new ArgumentOutOfRangeException("count");
ThrowIfDisposed();
if (count >= position) {
ReleaseBuffer();
buffer = Array.Empty<T>();
position = 0;
} else if (count > 0) {
int num = position - count;
T[] destinationArray = pool.Rent(num);
Array.Copy(buffer, count, destinationArray, 0, num);
ReleaseBuffer();
buffer = destinationArray;
position = num;
}
}
private protected override void Resize(int newSize)
{
T[] array = pool.Rent(newSize);
buffer.CopyTo(array, 0);
ReleaseBuffer();
buffer = array;
base.AllocationCounter?.WriteMetric((float)array.LongLength);
}
protected override void Dispose(bool disposing)
{
if (disposing) {
base.BufferSizeCallback?.Invoke(buffer.Length);
ReleaseBuffer();
buffer = Array.Empty<T>();
}
base.Dispose(disposing);
}
}
}