73 lines
2.6 KiB
C#
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}");
|
|
}
|
|
}
|
|
}
|