AyCode.Core/AyCode.Core/Serializers/ReferenceTracker.cs

139 lines
4.5 KiB
C#

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace AyCode.Core.Serializers;
/// <summary>
/// Shared reference tracking logic for serialization.
/// Tracks object references to enable $id/$ref handling for circular references.
/// </summary>
//public sealed class SerializationReferenceTracker
//{
// private readonly Dictionary<object, int> _scanOccurrences;
// private readonly Dictionary<object, string> _writtenRefs;
// private readonly HashSet<object> _multiReferenced;
// private int _nextId;
// public SerializationReferenceTracker(int initialCapacity = 32)
// {
// _scanOccurrences = new(initialCapacity, ReferenceEqualityComparer.Instance);
// _writtenRefs = new(initialCapacity, ReferenceEqualityComparer.Instance);
// _multiReferenced = new(initialCapacity, ReferenceEqualityComparer.Instance);
// _nextId = 1;
// }
// /// <summary>
// /// Tracks an object during the scanning phase.
// /// Returns true if this is the first occurrence (should continue scanning children).
// /// Returns false if object was seen before (multi-referenced).
// /// </summary>
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public bool TrackForScanning(object obj)
// {
// ref var count = ref CollectionsMarshal.GetValueRefOrAddDefault(_scanOccurrences, obj, out var exists);
// if (exists)
// {
// count++;
// _multiReferenced.Add(obj);
// return false;
// }
// count = 1;
// return true;
// }
// /// <summary>
// /// Checks if an object should have an $id written and returns the id.
// /// </summary>
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public bool ShouldWriteId(object obj, out string id)
// {
// if (_multiReferenced.Contains(obj) && !_writtenRefs.ContainsKey(obj))
// {
// id = _nextId++.ToString();
// return true;
// }
// id = "";
// return false;
// }
// /// <summary>
// /// Marks an object as written with its assigned id.
// /// </summary>
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public void MarkAsWritten(object obj, string id) => _writtenRefs[obj] = id;
// /// <summary>
// /// Tries to get an existing reference id for an object.
// /// If found, a $ref should be written instead of the full object.
// /// </summary>
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public bool TryGetExistingRef(object obj, out string refId)
// {
// return _writtenRefs.TryGetValue(obj, out refId!);
// }
// /// <summary>
// /// Clears all tracking data for reuse.
// /// </summary>
// public void Clear()
// {
// _scanOccurrences.Clear();
// _writtenRefs.Clear();
// _multiReferenced.Clear();
// _nextId = 1;
// }
//}
///// <summary>
///// Shared reference tracking logic for deserialization.
///// Resolves $id/$ref references during deserialization.
///// </summary>
//public sealed class DeserializationReferenceTracker
//{
// private Dictionary<string, object>? _idToObject;
// /// <summary>
// /// Registers an object with its $id.
// /// </summary>
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public void RegisterObject(string id, object obj)
// {
// _idToObject ??= new Dictionary<string, object>(64, StringComparer.Ordinal);
// _idToObject[id] = obj;
// }
// /// <summary>
// /// Tries to get a referenced object by its $id.
// /// </summary>
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public bool TryGetReferencedObject(string id, out object? obj)
// {
// if (_idToObject != null)
// return _idToObject.TryGetValue(id, out obj);
// obj = null;
// return false;
// }
// /// <summary>
// /// Clears all tracking data for reuse.
// /// </summary>
// public void Clear()
// {
// _idToObject?.Clear();
// }
//}
/// <summary>
/// Reference equality comparer for object identity comparison.
/// Used for reference tracking dictionaries.
/// </summary>
public sealed class ReferenceEqualityComparer : IEqualityComparer<object>
{
public static readonly ReferenceEqualityComparer Instance = new();
private ReferenceEqualityComparer() { }
public new bool Equals(object? x, object? y) => ReferenceEquals(x, y);
public int GetHashCode(object obj) => RuntimeHelpers.GetHashCode(obj);
}