using System.Collections;
using System.Runtime.CompilerServices;
namespace Penumbra.Api.Helpers;
/// A dictionary that implicitly can be converted to a read-only dictionary with different value type.
/// The type of the keys.
/// The actual type of the values.
/// The read-only type of the values.
public abstract class ConvertingDict(IReadOnlyDictionary dict)
: IReadOnlyDictionary
where TKey : notnull
{
/// Obtain the original dictionary.
public IReadOnlyDictionary Original
=> dict;
/// Conversion between values.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
protected abstract TValueTo ConvertValue(in TValueFrom from);
///
public bool ContainsKey(TKey key)
=> dict.ContainsKey(key);
///
public bool TryGetValue(TKey key, out TValueTo value)
{
if (dict.TryGetValue(key, out var v))
{
value = ConvertValue(v);
return true;
}
value = default!;
return false;
}
///
public TValueTo this[TKey key]
=> ConvertValue(dict[key]);
public IEnumerable Keys
=> dict.Keys;
///
public IEnumerable Values
{
get
{
foreach (var value in dict.Values)
yield return ConvertValue(value);
}
}
///
public int Count
=> dict.Count;
///
public IEnumerator> GetEnumerator()
{
foreach (var kvp in dict)
yield return new KeyValuePair(kvp.Key, ConvertValue(kvp.Value));
}
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
}
/// A dictionary that implicitly can be converted to a read-only dictionary with different value type.
/// The actual type of the keys.
/// The read-only type of the keys.
/// The actual type of the values.
/// The read-only type of the values.
public abstract class ConvertingDict(IReadOnlyDictionary dict)
: IReadOnlyDictionary
where TKeyFrom : notnull
where TKeyTo : notnull
{
/// Obtain the original dictionary.
public IReadOnlyDictionary Original
=> dict;
/// Conversion between keys.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
protected abstract TKeyTo ConvertKey(in TKeyFrom from);
/// Conversion between keys.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
protected abstract TKeyFrom ConvertKeyBack(in TKeyTo from);
/// Conversion between values.
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
protected abstract TValueTo ConvertValue(in TValueFrom from);
///
public bool ContainsKey(TKeyTo key)
=> dict.ContainsKey(ConvertKeyBack(key));
///
public bool TryGetValue(TKeyTo key, out TValueTo value)
{
if (dict.TryGetValue(ConvertKeyBack(key), out var v))
{
value = ConvertValue(v);
return true;
}
value = default!;
return false;
}
///
public TValueTo this[TKeyTo key]
=> ConvertValue(dict[ConvertKeyBack(key)]);
///
public IEnumerable Keys
{
get
{
foreach (var key in dict.Keys)
yield return ConvertKey(key);
}
}
///
public IEnumerable Values
{
get
{
foreach (var value in dict.Values)
yield return ConvertValue(value);
}
}
///
public IEnumerator> GetEnumerator()
{
foreach (var kvp in dict)
yield return new KeyValuePair(ConvertKey(kvp.Key), ConvertValue(kvp.Value));
}
///
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
///
public int Count
=> dict.Count;
}