using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace SharpGLTF.Memory
{
///
/// Special accessor to wrap over a base accessor and a sparse accessor
///
/// An unmanage structure type.
[System.Diagnostics.DebuggerDisplay("Sparse {typeof(T).Name} Accessor {Count}")]
public sealed class SparseArray : IAccessorArray
where T : unmanaged
{
#region lifecycle
public SparseArray(IReadOnlyList denseValues, IReadOnlyList sparseValues, IReadOnlyList sparseKeys)
{
Guard.NotNull(denseValues, nameof(denseValues));
Guard.NotNull(sparseValues, nameof(sparseValues));
Guard.NotNull(sparseKeys, nameof(sparseKeys));
Guard.MustBeEqualTo(sparseKeys.Count, sparseValues.Count, nameof(sparseKeys.Count));
Guard.MustBeLessThanOrEqualTo(sparseKeys.Count, denseValues.Count, nameof(sparseKeys.Count));
_DenseItems = denseValues;
_SparseItems = sparseValues;
// expand indices for fast access
_SparseIndices = new Dictionary();
for (int val = 0; val < sparseKeys.Count; ++val)
{
var key = (int)sparseKeys[val];
if (key >= denseValues.Count)
{
throw new ArgumentOutOfRangeException(nameof(sparseKeys));
}
_SparseIndices[key] = val;
}
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly IReadOnlyList _DenseItems;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly IReadOnlyList _SparseItems;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly Dictionary _SparseIndices;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private T[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _DenseItems.Count;
public bool IsReadOnly => true;
public T this[int index]
{
get => _SparseIndices.TryGetValue(index, out int topIndex) ? _SparseItems[topIndex] : _DenseItems[index];
set => throw new NotSupportedException("Collection is read only.");
}
public IEnumerator GetEnumerator() { return new EncodedArrayEnumerator(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator(this); }
public bool Contains(T item) { return IndexOf(item) >= 0; }
public int IndexOf(T item) { return this._FirstIndexOf(item); }
public void CopyTo(T[] array, int arrayIndex) { Guard.NotNull(array, nameof(array)); this._CopyTo(array, arrayIndex); }
void IList.Insert(int index, T item) { throw new NotSupportedException(); }
void IList.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection.Add(T item) { throw new NotSupportedException(); }
void ICollection.Clear() { throw new NotSupportedException(); }
bool ICollection.Remove(T item) { throw new NotSupportedException(); }
#endregion
}
}