using System.Collections; using System.Text.Json; namespace DeepDrftContent.FileDatabase.Utils; /// /// A map implementation that uses structural equality for keys by serializing them to JSON. /// This provides the same behavior as the TypeScript StructuralMap. /// /// The key type /// The value type public class StructuralMap : IEnumerable> { private readonly Dictionary> _innerMap = new(); /// /// Converts a key to its string representation for structural comparison /// private string GetKeyString(TKey key) { return key switch { null => "null", string s => s, int or long or float or double or decimal => key.ToString()!, _ => JsonSerializer.Serialize(key) }; } /// /// Sets a key-value pair in the map /// public StructuralMap Set(TKey key, TValue value) { var keyString = GetKeyString(key); _innerMap[keyString] = new KeyValuePair(key, value); return this; } /// /// Gets a value by key, or default if not found /// public TValue? Get(TKey key) { var keyString = GetKeyString(key); return _innerMap.TryGetValue(keyString, out var pair) ? pair.Value : default; } /// /// Checks if the map contains the specified key /// public bool Has(TKey key) { var keyString = GetKeyString(key); return _innerMap.ContainsKey(keyString); } /// /// Removes a key-value pair from the map /// public bool Delete(TKey key) { var keyString = GetKeyString(key); return _innerMap.Remove(keyString); } /// /// Clears all entries from the map /// public void Clear() => _innerMap.Clear(); /// /// Gets the number of entries in the map /// public int Size => _innerMap.Count; /// /// Enumerates all key-value pairs /// public IEnumerator> GetEnumerator() { return _innerMap.Values.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Gets all keys in the map /// public IEnumerable Keys => _innerMap.Values.Select(pair => pair.Key); /// /// Gets all values in the map /// public IEnumerable Values => _innerMap.Values.Select(pair => pair.Value); /// /// Executes a callback for each key-value pair /// public void ForEach(Action> callback) { foreach (var (key, value) in this) { callback(value, key, this); } } }