FileDatabase refactor for normalization and consistency

This commit is contained in:
daniel-c-harvey
2025-09-04 16:26:10 -04:00
parent e82366e47f
commit 6fefcbcfb5
24 changed files with 3069 additions and 186 deletions
@@ -6,25 +6,43 @@ namespace DeepDrftContent.FileDatabase.Utils;
/// <summary>
/// A map implementation that uses structural equality for keys by serializing them to JSON.
/// This provides the same behavior as the TypeScript StructuralMap.
/// Optimized with caching to avoid repeated serialization.
/// </summary>
/// <typeparam name="TKey">The key type</typeparam>
/// <typeparam name="TValue">The value type</typeparam>
public class StructuralMap<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
public class StructuralMap<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> where TKey : notnull
{
private readonly Dictionary<string, KeyValuePair<TKey, TValue>> _innerMap = new();
private readonly Dictionary<TKey, string> _keyStringCache = new();
/// <summary>
/// Converts a key to its string representation for structural comparison
/// Uses caching to avoid expensive serialization on repeated lookups
/// </summary>
private string GetKeyString(TKey key)
{
return key switch
if (key == null) return "null";
// For reference types, use cache to avoid repeated serialization
if (!typeof(TKey).IsValueType && _keyStringCache.TryGetValue(key, out var cached))
{
return cached;
}
var keyString = key switch
{
null => "null",
string s => s,
int or long or float or double or decimal => key.ToString()!,
_ => JsonSerializer.Serialize(key)
};
// Cache for reference types only (value types are cheap to convert)
if (!typeof(TKey).IsValueType)
{
_keyStringCache[key] = keyString;
}
return keyString;
}
/// <summary>
@@ -6,24 +6,42 @@ namespace DeepDrftContent.FileDatabase.Utils;
/// <summary>
/// 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.
/// </summary>
/// <typeparam name="T">The value type</typeparam>
public class StructuralSet<T> : IEnumerable<T>
public class StructuralSet<T> : IEnumerable<T> where T : notnull
{
private readonly Dictionary<string, T> _innerMap = new();
private readonly Dictionary<T, string> _valueStringCache = new();
/// <summary>
/// Converts a value to its string representation for structural comparison
/// Uses caching to avoid expensive serialization on repeated lookups
/// </summary>
private string GetValueString(T value)
{
return value switch
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
{
null => "null",
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;
}
/// <summary>