PkmnLibRSharp/PkmnLibRSharp/StaticData/Libraries/DataLibrary.cs

101 lines
2.7 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using PkmnLibSharp.FFI;
using PkmnLibSharp.Utils;
namespace PkmnLibSharp.StaticData.Libraries
{
public abstract class DataLibrary<T> : ExternPointer<DataLibrary<T>.CacheData>, IReadOnlyDictionary<string, T>
{
protected DataLibrary(IdentifiablePointer ptr, bool isOwner) : base(ptr, isOwner)
{
}
public class CacheData
{
public List<string>? KeyCache { get; internal set; }
public Dictionary<string, T> ValueCache { get; } = new();
}
public abstract void Add(string key, T value);
public abstract int Count { get; }
protected abstract T? GetValueByKey(string key);
public bool ContainsKey(string key)
{
return GetValueByKey(key) != null;
}
public bool TryGetValue(string key, [NotNullWhen(true)] out T value)
{
if (Cache.ValueCache.TryGetValue(key, out value) && value != null)
return true;
var v = GetValueByKey(key);
if (v != null)
{
Cache.ValueCache.Add(key, v);
value = v;
}
return v != null;
}
public T this[string key]
{
get
{
if (!TryGetValue(key, out var value))
throw new KeyNotFoundException($"Value with key `{key}` was not found");
return value!;
}
}
public abstract string? GetKeyByIndex(ulong index);
public IEnumerable<string> Keys
{
get
{
if (Cache.KeyCache == null)
{
Cache.KeyCache = new List<string>(Count);
for (ulong i = 0; i < (ulong)Count; i++)
{
var key = GetKeyByIndex(i);
if (key == null)
break;
Cache.KeyCache.Add(key);
}
}
return Cache.KeyCache;
}
}
public IEnumerable<T> Values
{
get { return Keys.Select(key => this[key]); }
}
protected override CacheData CreateCache() => new();
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
{
return Keys.Select(key => new KeyValuePair<string, T>(key, this[key])).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
~DataLibrary()
{
Dispose();
}
}
}