using System; using System.Buffers; using System.Runtime.InteropServices; using SixLabors.Memory; namespace SixLabors.ImageSharp.Tests.Memory { internal class TestMemoryAllocator : MemoryAllocator { public TestMemoryAllocator(byte dirtyValue = 42) { this.DirtyValue = dirtyValue; } /// /// The value to initilazie the result buffer with, with non-clean options () /// public byte DirtyValue { get; } public override IMemoryOwner Allocate(int length, AllocationOptions options = AllocationOptions.None) { T[] array = this.AllocateArray(length, options); return new BasicArrayBuffer(array, length); } public override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options = AllocationOptions.None) { byte[] array = this.AllocateArray(length, options); return new ManagedByteBuffer(array); } private T[] AllocateArray(int length, AllocationOptions options) where T : struct { var array = new T[length + 42]; if (options == AllocationOptions.None) { Span data = MemoryMarshal.Cast(array.AsSpan()); data.Fill(this.DirtyValue); } return array; } /// /// Wraps an array as an instance. /// private class BasicArrayBuffer : MemoryManager where T : struct { private GCHandle pinHandle; /// /// Initializes a new instance of the class /// /// The array /// The length of the buffer public BasicArrayBuffer(T[] array, int length) { DebugGuard.MustBeLessThanOrEqualTo(length, array.Length, nameof(length)); this.Array = array; this.Length = length; } /// /// Initializes a new instance of the class /// /// The array public BasicArrayBuffer(T[] array) : this(array, array.Length) { } /// /// Gets the array /// public T[] Array { get; } /// /// Gets the length /// public int Length { get; } /// public override Span GetSpan() => this.Array.AsSpan(0, this.Length); public override unsafe MemoryHandle Pin(int elementIndex = 0) { if (!this.pinHandle.IsAllocated) { this.pinHandle = GCHandle.Alloc(this.Array, GCHandleType.Pinned); } void* ptr = (void*)this.pinHandle.AddrOfPinnedObject(); return new MemoryHandle(ptr, this.pinHandle); } public override void Unpin() { throw new NotImplementedException(); } /// protected override void Dispose(bool disposing) { } } private class ManagedByteBuffer : BasicArrayBuffer, IManagedByteBuffer { public ManagedByteBuffer(byte[] array) : base(array) { } } } }