namespace ALttPRandomizer.Serialization { using System; using System.Collections.Generic; using System.Reflection; using System.Text.Json.Serialization; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; public class YamlStringEnumConverter : IYamlTypeConverter { private readonly Dictionary> deserializationMap; private readonly Dictionary> serializationMap; public YamlStringEnumConverter() { this.deserializationMap = new(); this.serializationMap = new(); } public bool Accepts(Type type) => type.IsEnum; private void RegisterType(Type type) { if (this.serializationMap.ContainsKey(type) && this.deserializationMap.ContainsKey(type)) { return; } this.deserializationMap[type] = new(); this.serializationMap[type] = new(); var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) { var alias = UnderscoredNamingConvention.Instance.Apply(field.Name); var value = Enum.Parse(type, field.Name); var att = field.GetCustomAttribute(); if (att != null) { alias = att.Name; } this.deserializationMap[type][alias] = value; this.serializationMap[type][value] = alias; } } public object? ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer) { this.RegisterType(type); var stringValue = parser.Consume().Value; if (this.deserializationMap[type].TryGetValue(stringValue, out var value)) { return value; } throw new YamlException($"Invalid value \"{stringValue}\" for type {type}"); } public void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer) { this.RegisterType(type); if (value is null) { throw new YamlException($"Unexpected null value of type {type}"); } if (this.serializationMap[type].TryGetValue(value, out var stringValue)) { emitter.Emit(new Scalar(stringValue)); return; } throw new YamlException($"Invalid value \"{value}\" for type {type}"); } } }