Skip to content

Instantly share code, notes, and snippets.

@dadhi
Forked from kolebynov/Program.cs
Created May 7, 2024 13:27
Show Gist options
  • Save dadhi/068e964d6b1747d82ecf9e2314f0cf6d to your computer and use it in GitHub Desktop.
Save dadhi/068e964d6b1747d82ecf9e2314f0cf6d to your computer and use it in GitHub Desktop.
Simple stack/heap dynamic array
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
var list1 = new FixedList16<int>();
var list2 = new FixedList32<int>();
UseList(ref list1, 1);
UseList(ref list2, 2);
static void UseList<TItem, TList>(ref TList list, TItem item)
where TItem : unmanaged
where TList : IFixedList<TItem>
{
list.Add(item);
}
public interface IFixedList<T>
where T : unmanaged
{
int Count { get; }
ref T GetRef(int index);
void Add(T item);
}
public struct FixedListImpl<TElement, TBuffer>
where TElement : unmanaged
where TBuffer : unmanaged
{
private static readonly int BufferSize = Unsafe.SizeOf<TBuffer>();
private TBuffer _buffer;
private TElement[] _heapBuffer;
private int _count;
public int Count => _count;
public ref TElement GetRef(int index)
{
// CheckIndex
return ref _heapBuffer != null
? ref _heapBuffer[index]
: ref MemoryMarshal.Cast<TBuffer, TElement>(MemoryMarshal.CreateSpan(ref _buffer, 1))[index];
}
public void Add(TElement item)
{
var span = MemoryMarshal.Cast<TBuffer, TElement>(MemoryMarshal.CreateSpan(ref _buffer, 1));
if (_heapBuffer == null && span.Length > _count)
{
span[_count++] = item;
return;
}
_heapBuffer ??= new TElement[16];
// Reallocate heap buffer if needed
_heapBuffer[_count++] = item;
}
}
public struct FixedList16<T> : IFixedList<T>
where T : unmanaged
{
private FixedListImpl<T, Buffer16> _impl;
public int Count => _impl.Count;
public ref T GetRef(int index) => ref _impl.GetRef(index);
public void Add(T item) => _impl.Add(item);
}
public struct FixedList32<T> : IFixedList<T>
where T : unmanaged
{
private FixedListImpl<T, Buffer32> _impl;
public int Count => _impl.Count;
public ref T GetRef(int index) => ref _impl.GetRef(index);
public void Add(T item) => _impl.Add(item);
}
[InlineArray(16)]
public struct Buffer16
{
private byte _element0;
}
[InlineArray(32)]
public struct Buffer32
{
private byte _element0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment