using System;
using Unity.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Unity.Collections.LowLevel.Unsafe;
using System.Collections.Generic;
using Unity.Burst;
namespace UnityEngine.U2D.Common.UTess
{
///
/// Array. Used within UTess and constrained to
/// 1. Auto-resizes upto the Max count with a smaller initial count.
/// 2. Only be used within the created thread. Read 1.
/// 3. Read/Write access are all fast-paths.
/// 4. Mostly used with Temp Alloc within UTess ontext.
///
///
[StructLayout(LayoutKind.Sequential)]
[DebuggerDisplay("Length = {Length}")]
[DebuggerTypeProxy(typeof(ArrayDebugView<>))]
internal unsafe struct Array : IDisposable where T : struct
{
internal NativeArray m_Array;
internal int m_MaxSize;
internal Allocator m_AllocLabel;
internal NativeArrayOptions m_Options;
public Array(int length, int maxSize, Allocator allocMode, NativeArrayOptions options)
{
m_Array = new NativeArray(length, allocMode, options);
m_AllocLabel = allocMode;
m_Options = options;
m_MaxSize = maxSize;
}
private void ResizeIfRequired(int index)
{
if (index >= m_MaxSize || index < 0)
throw new IndexOutOfRangeException(
$"Trying to access beyond allowed size. {index} is out of range of '{m_MaxSize}' MaxSize.");
if (index < m_Array.Length)
return;
int requiredSize = Length;
while (requiredSize <= index)
requiredSize = requiredSize * 2;
requiredSize = requiredSize > m_MaxSize ? m_MaxSize : requiredSize;
var copyArray = new NativeArray(requiredSize, m_AllocLabel, m_Options);
NativeArray.Copy(m_Array, copyArray, Length);
m_Array.Dispose();
m_Array = copyArray;
}
public unsafe T this[int index]
{
get
{
return m_Array[index];
}
set
{
ResizeIfRequired(index);
m_Array[index] = value;
}
}
public bool IsCreated => m_Array.IsCreated;
public int Length => (m_MaxSize != 0) ? m_Array.Length : 0;
public void Dispose()
{
m_Array.Dispose();
m_MaxSize = 0;
}
public void* UnsafePtr
{
get
{
return m_Array.GetUnsafePtr();
}
}
public void* UnsafeReadOnlyPtr
{
get
{
return m_Array.GetUnsafeReadOnlyPtr();
}
}
// Should only ever be used for Debugging.
public void CopyTo(T[] array)
{
m_Array.CopyTo(array);
}
}
///
/// DebuggerTypeProxy for
///
internal sealed class ArrayDebugView where T : struct
{
private Array array;
public ArrayDebugView(Array array)
{
this.array = array;
}
public T[] Items
{
get
{
var ret = new T[array.Length];
array.CopyTo(ret);
return ret;
}
}
}
}