139 lines
4.5 KiB
C#
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);
|
|
}
|