namespace ALttPRandomizer.Serialization { using System; using System.Collections.Generic; using ALttPRandomizer.Model; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; public class RandomizableWeightsYamlConverters : IYamlTypeConverter { private readonly Dictionary converters = new(); public bool Accepts(Type type) { if (this.converters.ContainsKey(type)) { return true; } if (!type.IsGenericType) { return false; } if (type.GetGenericTypeDefinition() != typeof(RandomizableWeights<>)) { return false; } Type itemType = type.GetGenericArguments()[0]; Type innerType = typeof(RandomizableWeightsYamlConverter<>).MakeGenericType(itemType)!; this.converters[type] = (IYamlTypeConverter) Activator.CreateInstance(innerType)!; return true; } public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { return this.converters[type].ReadYaml(parser, type, rootDeserializer); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { this.converters[type].WriteYaml(emitter, value, type, serializer); } } internal class RandomizableWeightsYamlConverter : IYamlTypeConverter where T : struct, Enum { private readonly Type valueType; private readonly Type dictionaryType; public RandomizableWeightsYamlConverter() { this.valueType = typeof(T); this.dictionaryType = typeof(IDictionary); } public bool Accepts(Type type) { return type == typeof(RandomizableWeights); } public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { if (parser.Accept(out var evt)) { if (evt.Value == "null") { parser.Consume(); return RandomizableWeights.EmptyWeights; } var value = rootDeserializer.Invoke(this.valueType); if (value is T t) { return RandomizableWeights.ConstantWeights(t); } else { return RandomizableWeights.EmptyWeights; } } if (parser.Accept(out _)) { var value = rootDeserializer.Invoke(this.dictionaryType); if (value is IDictionary dict) { return RandomizableWeights.FromDictionary(dict); } else { return RandomizableWeights.EmptyWeights; } } throw new YamlException($"Error reading type RandomizableWeights<{typeof(T).Name}>."); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { if (value is RandomizableWeights weights) { switch (weights.Options.Count) { case 0: emitter.Emit(new Scalar("null")); break; case 1: serializer.Invoke(weights.Options[0].Item, valueType); break; default: emitter.Emit(new MappingStart()); foreach (var (item, weight) in weights.Options) { serializer.Invoke(item, valueType); emitter.Emit(new Scalar(weight.ToString())); } emitter.Emit(new MappingEnd()); break; } } else { emitter.Emit(new MappingStart()); emitter.Emit(new MappingEnd()); } } } }