Files
alttpr-backend/ALttPRandomizer/Serialization/YamlStringEnumConverter.cs

73 lines
2.6 KiB
C#

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<Type, Dictionary<string, object>> deserializationMap;
private readonly Dictionary<Type, Dictionary<object, string>> 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<JsonStringEnumMemberNameAttribute>();
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<Scalar>().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}");
}
}
}