PoolingArrayBufferWriter<T>
public sealed class PoolingArrayBufferWriter<T> : BufferWriter<T>, ISupplier<ArraySegment<T>>, IFunctional<Func<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 DotNext.Runtime.CompilerServices;
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DotNext.Buffers
{
[NullableContext(1)]
[Nullable(new byte[] {
0,
1
})]
public sealed class PoolingArrayBufferWriter<[Nullable(2)] T> : BufferWriter<T>, ISupplier<ArraySegment<T>>, IFunctional<Func<ArraySegment<T>>>, IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable
{
private readonly ArrayPool<T> pool = pool ?? ArrayPool<T>.Shared;
private T[] buffer = Array.Empty<T>();
int ICollection<T>.Count {
get {
return base.WrittenCount;
}
}
bool ICollection<T>.IsReadOnly {
get {
return false;
}
}
public new ref T this[int index] {
get {
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, (uint)position, "index");
return ref Unsafe.Add<T>(ref MemoryMarshal.GetArrayDataReference<T>(buffer), index);
}
}
T IList<T>.this[int index] {
get {
return this[index];
}
set {
this[index] = value;
}
}
public override int Capacity {
get {
return buffer.Length;
}
set {
if (value < 0)
throw new ArgumentOutOfRangeException("value");
if (value > 0)
buffer = pool.Rent(value);
}
}
[Nullable(new byte[] {
0,
1
})]
public override ReadOnlyMemory<T> WrittenMemory {
[return: Nullable(new byte[] {
0,
1
})]
get {
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
return new ReadOnlyMemory<T>(buffer, 0, position);
}
}
[Nullable(new byte[] {
0,
1
})]
public ArraySegment<T> WrittenArray {
[return: Nullable(new byte[] {
0,
1
})]
get {
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
return new ArraySegment<T>(buffer, 0, position);
}
}
public PoolingArrayBufferWriter([Nullable(new byte[] {
2,
1
})] ArrayPool<T> pool = null)
{
}
void ICollection<T>.CopyTo(T[] array, int arrayIndex)
{
MemoryMarshal.CreateReadOnlySpan<T>(ref MemoryMarshal.GetArrayDataReference<T>(buffer), position).CopyTo(MemoryExtensions.AsSpan<T>(array, arrayIndex));
}
int IList<T>.IndexOf(T item)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
return Array.IndexOf<T>(buffer, item, 0, position);
}
bool ICollection<T>.Contains(T item)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
return Array.IndexOf<T>(buffer, item, 0, position) >= 0;
}
private void RemoveAt(int index)
{
CopyFast(buffer, index + 1, buffer, index, position - index - 1);
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
buffer[position - 1] = default(T);
if (--position == 0) {
ReturnBuffer();
buffer = Array.Empty<T>();
}
}
void IList<T>.RemoveAt(int index)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual<uint>((uint)index, (uint)position, "index");
RemoveAt(index);
}
bool ICollection<T>.Remove(T item)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
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, new ReadOnlySpan<T>(ref item));
}
public unsafe void Insert(int index, [Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> items)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)index, (uint)position, "index");
if (!items.IsEmpty) {
if (buffer.GetLength() == (UIntPtr)(void*)null)
buffer = pool.Rent(items.Length);
else if ((ulong)(uint)(position + items.Length) <= (ulong)buffer.GetLength()) {
CopyFast(buffer, index, buffer, index + items.Length, position - index);
} else {
T[] destination = pool.Rent(buffer.Length + items.Length);
CopyFast(buffer, destination, index);
CopyFast(buffer, index, destination, index + items.Length, buffer.Length - index);
ReturnBuffer();
buffer = destination;
}
items.CopyTo(MemoryExtensions.AsSpan<T>(buffer, index));
position += items.Length;
}
}
public unsafe void Overwrite(int index, [Nullable(new byte[] {
0,
1
})] ReadOnlySpan<T> items)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)index, (uint)position, "index");
if (buffer.GetLength() == (UIntPtr)(void*)null)
buffer = pool.Rent(items.Length);
else if ((ulong)(uint)(index + items.Length) <= (ulong)buffer.GetLength()) {
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
Array.Clear(buffer, index, position - index);
} else {
T[] destination = pool.Rent(index + items.Length);
CopyFast(buffer, destination, index);
ReturnBuffer();
buffer = destination;
}
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;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReturnBuffer()
{
pool.Return(buffer, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
}
public unsafe override void Clear(bool reuseBuffer = false)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
if (buffer.GetLength() != (UIntPtr)(void*)null) {
if (!reuseBuffer) {
ReturnBuffer();
buffer = Array.Empty<T>();
} else if (RuntimeHelpers.IsReferenceOrContainsReferences<T>()) {
Array.Clear(buffer, 0, position);
}
}
position = 0;
}
[return: Nullable(new byte[] {
0,
1
})]
public override MemoryOwner<T> DetachBuffer()
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
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;
}
private T[] GetRawArray(int sizeHint)
{
ArgumentOutOfRangeException.ThrowIfNegative<int>(sizeHint, "sizeHint");
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
CheckAndResizeBuffer(sizeHint);
return buffer;
}
[return: Nullable(new byte[] {
0,
1
})]
public override Memory<T> GetMemory(int sizeHint = 0)
{
return MemoryExtensions.AsMemory<T>(GetRawArray(sizeHint), position);
}
[return: Nullable(new byte[] {
0,
1
})]
public override Span<T> GetSpan(int sizeHint = 0)
{
T[] rawArray = GetRawArray(sizeHint);
return MemoryMarshal.CreateSpan<T>(ref Unsafe.Add<T>(ref MemoryMarshal.GetArrayDataReference<T>(rawArray), position), rawArray.Length - position);
}
[return: Nullable(new byte[] {
0,
1
})]
public ArraySegment<T> GetArray(int sizeHint = 0)
{
return new ArraySegment<T>(GetRawArray(sizeHint), position, base.FreeCapacity);
}
public override void AddAll(ICollection<T> items)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
int count = items.Count;
if (count > 0) {
CheckAndResizeBuffer(count);
items.CopyTo(buffer, position);
position += count;
}
}
public unsafe void RemoveLast(int count)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
ArgumentOutOfRangeException.ThrowIfNegative<int>(count, "count");
if (buffer.GetLength() != (UIntPtr)(void*)null) {
if (count >= position) {
ReturnBuffer();
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 unsafe void RemoveFirst(int count)
{
ObjectDisposedException.ThrowIf(base.IsDisposed, (object)this);
ArgumentOutOfRangeException.ThrowIfNegative<int>(count, "count");
if (buffer.GetLength() != (UIntPtr)(void*)null) {
if (count >= position) {
ReturnBuffer();
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);
ReturnBuffer();
buffer = destinationArray;
position = num;
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CopyFast(T[] source, T[] destination, int length)
{
ReadOnlySpan<T> readOnlySpan = MemoryMarshal.CreateReadOnlySpan<T>(ref MemoryMarshal.GetArrayDataReference<T>(source), length);
Span<T> destination2 = MemoryMarshal.CreateSpan<T>(ref MemoryMarshal.GetArrayDataReference<T>(destination), length);
readOnlySpan.CopyTo(destination2);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void CopyFast(T[] source, int sourceIndex, T[] destination, int destinationIndex, int length)
{
ReadOnlySpan<T> readOnlySpan = MemoryMarshal.CreateReadOnlySpan<T>(ref Unsafe.Add<T>(ref MemoryMarshal.GetArrayDataReference<T>(source), sourceIndex), length);
Span<T> destination2 = MemoryMarshal.CreateSpan<T>(ref Unsafe.Add<T>(ref MemoryMarshal.GetArrayDataReference<T>(destination), destinationIndex), length);
readOnlySpan.CopyTo(destination2);
}
private protected unsafe override void Resize(int newSize)
{
T[] array = pool.Rent(newSize);
if (buffer.GetLength() != (UIntPtr)(void*)null) {
CopyFast(buffer, array, position);
ReturnBuffer();
}
buffer = array;
<PoolingArrayBufferWriter>FDA5BBF4E667473AEB3E690976E04ABB18D2410DFFD7065711E010FA78152906B__PoolingArrayBufferWriter.AllocationMeter.Record(array.LongLength, ref measurementTags);
}
protected unsafe override void Dispose(bool disposing)
{
if (disposing && buffer.GetLength() != (UIntPtr)(void*)null) {
ReturnBuffer();
buffer = Array.Empty<T>();
}
base.Dispose(disposing);
}
}
}