using System; using System.Collections.Generic; using System.Linq; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; namespace Syntriax.Engine.Core.Serialization; public class UniverseSerializer : IEngineTypeYamlSerializer { private const string SERIALIZED_SCALAR_NAME = "Properties"; public bool Accepts(Type type) => typeof(IUniverse).IsAssignableFrom(type); public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { string id; IUniverse universe; IStateEnable stateEnable; List universeObjects; parser.Consume(); if (parser.Consume().Value.CompareTo(nameof(IUniverse.Id)) != 0) throw new(); id = parser.Consume().Value; if (parser.Consume().Value.CompareTo(SERIALIZED_SCALAR_NAME) != 0) throw new(); SerializedClass instanceSerializedClass = (SerializedClass)rootDeserializer(typeof(SerializedClass))!; universe = (IUniverse)instanceSerializedClass.CreateInstance(); if (parser.Consume().Value.CompareTo(nameof(IUniverse.StateEnable)) != 0) throw new(); stateEnable = (IStateEnable)rootDeserializer(typeof(IStateEnable))!; if (parser.Consume().Value.CompareTo(nameof(IUniverse.UniverseObjects)) != 0) throw new(); universeObjects = (List)rootDeserializer(typeof(List))!; parser.Consume(); universe.Id = id; stateEnable.Assign(universe); universe.Assign(stateEnable); foreach (IUniverseObject uo in universeObjects) universe.Register(uo); return universe; } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { IUniverse universe = (IUniverse)value!; IEnumerable rootUniverseObjects = universe.UniverseObjects .Select(uo => { IUniverseObject root = uo; while (root.Parent is IUniverseObject parent) root = parent; return root; }) .Where(uo => !uo.GetType().HasAttribute()) .Distinct(); emitter.Emit(new MappingStart()); emitter.Emit(new Scalar(nameof(IUniverse.Id))); emitter.Emit(new Scalar(universe.Id)); emitter.Emit(new Scalar(SERIALIZED_SCALAR_NAME)); serializer(new SerializedClass(universe)); emitter.Emit(new Scalar(nameof(IUniverse.StateEnable))); serializer(universe.StateEnable); emitter.Emit(new Scalar(nameof(IUniverse.UniverseObjects))); serializer(rootUniverseObjects); emitter.Emit(new MappingEnd()); } }