using System.Collections;
using System.Text.Json;
namespace DeepDrftContent.Data.FileDatabase.Utils;
///
/// A set implementation that uses structural equality for values by serializing them to JSON.
/// This provides the same behavior as the TypeScript StructuralSet.
/// Optimized with caching to avoid repeated serialization.
///
/// The value type
public class StructuralSet : IEnumerable where T : notnull
{
private readonly Dictionary _innerMap = new();
private readonly Dictionary _valueStringCache = new();
///
/// Converts a value to its string representation for structural comparison
/// Uses caching to avoid expensive serialization on repeated lookups
///
private string GetValueString(T value)
{
if (value == null) return "null";
// For reference types, use cache to avoid repeated serialization
if (!typeof(T).IsValueType && _valueStringCache.TryGetValue(value, out var cached))
{
return cached;
}
var valueString = value switch
{
string s => s,
int or long or float or double or decimal => value.ToString()!,
_ => JsonSerializer.Serialize(value)
};
// Cache for reference types only (value types are cheap to convert)
if (!typeof(T).IsValueType)
{
_valueStringCache[value] = valueString;
}
return valueString;
}
///
/// Adds a value to the set
///
public StructuralSet Add(T value)
{
var valueString = GetValueString(value);
if (!_innerMap.ContainsKey(valueString))
{
_innerMap[valueString] = value;
}
return this;
}
///
/// Checks if the set contains the specified value
///
public bool Has(T value)
{
var valueString = GetValueString(value);
return _innerMap.ContainsKey(valueString);
}
///
/// Removes a value from the set
///
public bool Delete(T value)
{
var valueString = GetValueString(value);
return _innerMap.Remove(valueString);
}
///
/// Clears all values from the set
///
public void Clear() => _innerMap.Clear();
///
/// Gets the number of values in the set
///
public int Size => _innerMap.Count;
///
/// Enumerates all values in the set
///
public IEnumerator GetEnumerator()
{
return _innerMap.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
///
/// Gets all values in the set
///
public IEnumerable Values => _innerMap.Values;
}