mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
119 lines
4.2 KiB
C#
119 lines
4.2 KiB
C#
#nullable enable
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using GlitchyEngine.Core;
|
|
using GlitchyEngine.Extensions;
|
|
|
|
namespace GlitchyEngine.Serialization;
|
|
|
|
/// <summary>
|
|
/// Provides Serialization and Deserialization for Dictionaries.
|
|
/// </summary>
|
|
[CustomSerializer(typeof(Dictionary<,>))]
|
|
public static class DictionarySerializer
|
|
{
|
|
/// <summary>
|
|
/// Serializes a given Dictionary as a field of <see cref="container"/>.
|
|
/// </summary>
|
|
/// <param name="container">The parent object.</param>
|
|
/// <param name="fieldName">Name of the field in <see cref="container"/></param>
|
|
/// <param name="fieldValue">The dictionary</param>
|
|
/// <param name="fieldType">Type of <see cref="fieldValue"/> or the type of the field if <see cref="fieldValue"/> is <see langword="null"/></param>
|
|
public static void Serialize(SerializedObject container, string fieldName, object? fieldValue, Type fieldType)
|
|
{
|
|
if (fieldValue == null)
|
|
{
|
|
// Write a null pointer early out
|
|
container.AddValueTypeField(fieldName, SerializationType.ObjectReference, UUID.Zero);
|
|
return;
|
|
}
|
|
|
|
// Get a container for our dictionary (Note: container is our parent object).
|
|
// isNewContext is true, if our dictionary wasn't serialized so far.
|
|
var (context, isNewContext) = container.GetSerializedObject(fieldValue);
|
|
|
|
if (isNewContext)
|
|
{
|
|
Type keyType = fieldType.GetGenericArguments()[0];
|
|
Type valueType = fieldType.GetGenericArguments()[1];
|
|
|
|
IDictionary dictionary = (IDictionary)fieldValue;
|
|
ICollection collection = (ICollection)fieldValue;
|
|
|
|
context.AddValueTypeField("Count", SerializationType.Int32, collection.Count);
|
|
|
|
int index = 0;
|
|
|
|
foreach (DictionaryEntry entry in dictionary)
|
|
{
|
|
context.PushScope(index.ToString());
|
|
|
|
context.SerializeField("Key", entry.Key, keyType);
|
|
context.SerializeField("Value", entry.Value, valueType);
|
|
|
|
context.PopScope();
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
// Write the reference to our dictionary into the field of the parent.
|
|
container.AddValueTypeField(fieldName, SerializationType.ObjectReference, context.Id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deserializes a dictionary that is a field of the given <see cref="container"/>.
|
|
/// </summary>
|
|
/// <param name="container">The parent object whose field with <see cref="fieldName"/> is a dictionary.</param>
|
|
/// <param name="fieldName">The name of the field.</param>
|
|
/// <param name="fieldType">The type of the field.</param>
|
|
/// <returns></returns>
|
|
public static object? Deserialize(DeserializationObject container, string fieldName, Type fieldType)
|
|
{
|
|
UUID id = container.GetFieldValue<UUID>(fieldName, SerializationType.ObjectReference);
|
|
|
|
if (id == UUID.Zero)
|
|
return null;
|
|
|
|
// Get serialization container for the instance
|
|
DeserializationObject? deserializedObject = container.GetDeserializedObject(id);
|
|
|
|
Type? type = deserializedObject?.StoredType;
|
|
|
|
if (type?.IsAssignableTo(fieldType) != true)
|
|
return DeserializationObject.NoValueDeserialized;
|
|
|
|
Type keyType = fieldType.GetGenericArguments()[0];
|
|
Type valueType = fieldType.GetGenericArguments()[1];
|
|
|
|
int count = deserializedObject!.GetFieldValue<int>("Count", SerializationType.Int32);
|
|
|
|
// Create instance, pass in capacity
|
|
object? instance = ActivatorExtension.CreateInstanceSafe(type, count);
|
|
|
|
Debug.Assert(instance != null);
|
|
|
|
IDictionary dictionary = (IDictionary)instance!;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
deserializedObject.PushScope(i.ToString());
|
|
|
|
object? key = deserializedObject.DeserializeField(null, keyType, "Key");
|
|
object? value = deserializedObject.DeserializeField(null, valueType, "Value");
|
|
|
|
if (key != null)
|
|
{
|
|
dictionary.Add(key, value);
|
|
}
|
|
|
|
deserializedObject.PopScope();
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
}
|