using System; using System.Collections.Generic; using System.Linq; using Engine.Core; using Engine.Core.Factory; using Engine.Core.Serialization; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; namespace Engine.Serializers.Yaml; public class SerializedClassConverter : EngineTypeYamlSerializerBase { public override SerializedClass? Read(IParser parser, Type type, ObjectDeserializer rootDeserializer) { bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); ProgressionTracker.Set(isTrackingController ? .1f : ProgressionTracker.Progression, $"Reading class"); SerializedClass serializedClass = new(); Dictionary publicDictionary = []; Dictionary privateDictionary = []; parser.Consume(); while (!parser.TryConsume(out _)) { string key = parser.Consume().Value; switch (key) { case nameof(SerializedClass.Type): serializedClass.Type = parser.Consume().Value; break; case nameof(SerializedClass.Public): publicDictionary = (Dictionary)rootDeserializer(typeof(Dictionary))!; break; case nameof(SerializedClass.Private): privateDictionary = (Dictionary)rootDeserializer(typeof(Dictionary))!; break; } } Type classType = TypeFactory.GetType(serializedClass.Type); foreach ((string key, object @object) in publicDictionary) if (@object is TypeContainer typeContainer) serializedClass.Public.Add(key, Serializer.InternalDeserialize(typeContainer.Value!.ToString()!, TypeFactory.GetType(typeContainer.Type))); else serializedClass.Public.Add(key, Serializer.InternalDeserialize(@object.ToString()!, (classType.GetProperty(key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)?.PropertyType ?? classType.GetField(key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)?.FieldType)!)); foreach ((string key, object @object) in privateDictionary) if (@object is TypeContainer typeContainer) serializedClass.Private.Add(key, Serializer.InternalDeserialize(typeContainer.Value!.ToString()!, TypeFactory.GetType(typeContainer.Type))); else serializedClass.Private.Add(key, Serializer.InternalDeserialize(@object.ToString()!, (classType.GetProperty(key, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Default)?.PropertyType ?? classType.GetField(key, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Default)?.FieldType)!)); ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Read {serializedClass.Type}"); return serializedClass; } public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { SerializedClass serializedClass = (SerializedClass)value!; bool isTrackingController = ProgressionTracker.Progression.ApproximatelyEquals(0f); ProgressionTracker.Set(isTrackingController ? .25f : ProgressionTracker.Progression, $"Serializing {serializedClass.Type}"); Dictionary publics = []; Dictionary privates = []; foreach ((string key, object? @object) in serializedClass.Public.Where(v => !v.GetType().HasAttribute())) if (@object?.GetType().IsClass == false) publics.Add(key, @object!); else publics.Add(key, new TypeContainer(@object)); foreach ((string key, object? @object) in serializedClass.Private.Where(v => !v.GetType().HasAttribute())) if (@object?.GetType().IsClass == false) privates.Add(key, @object!); else privates.Add(key, new TypeContainer(@object)); emitter.Emit(new MappingStart()); emitter.Emit(new Scalar(nameof(SerializedClass.Type))); emitter.Emit(new Scalar(serializedClass.Type)); if (publics.Count > 0) { emitter.Emit(new Scalar(nameof(SerializedClass.Public))); serializer(publics); } if (privates.Count > 0) { emitter.Emit(new Scalar(nameof(SerializedClass.Private))); serializer(privates); } ProgressionTracker.Set(isTrackingController ? 1f : ProgressionTracker.Progression, $"Serialized {serializedClass.Type}"); emitter.Emit(new MappingEnd()); } }