83 lines
3.7 KiB
C#
83 lines
3.7 KiB
C#
namespace ALttPRandomizer.Serialization {
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using ALttPRandomizer.Model;
|
|
|
|
public class RandomizableWeightsJsonConverter : JsonConverterFactory {
|
|
public override bool CanConvert(Type typeToConvert) {
|
|
if (!typeToConvert.IsGenericType) {
|
|
return false;
|
|
}
|
|
|
|
if (typeToConvert.GetGenericTypeDefinition() != typeof(RandomizableWeights<>)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) {
|
|
Type itemType = typeToConvert.GetGenericArguments()[0];
|
|
Type innerType = typeof(RandomizableWeightsConverterInner<>).MakeGenericType(itemType);
|
|
|
|
return (JsonConverter) Activator.CreateInstance(innerType, args: options)!;
|
|
}
|
|
|
|
private class RandomizableWeightsConverterInner<T> : JsonConverter<RandomizableWeights<T>> where T : struct, Enum {
|
|
private readonly JsonConverter<IDictionary<T, int>> dictionaryConverter;
|
|
private readonly JsonConverter<T> valueConverter;
|
|
private readonly Type valueType;
|
|
private readonly Type dictionaryType;
|
|
|
|
public RandomizableWeightsConverterInner(JsonSerializerOptions options) {
|
|
dictionaryConverter = (JsonConverter<IDictionary<T, int>>) options.GetConverter(typeof(IDictionary<T, int>));
|
|
valueConverter = (JsonConverter<T>) options.GetConverter(typeof(T));
|
|
|
|
this.valueType = typeof(T);
|
|
this.dictionaryType = typeof(IDictionary<T, int>);
|
|
}
|
|
|
|
public override RandomizableWeights<T>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
|
switch (reader.TokenType) {
|
|
case JsonTokenType.Null:
|
|
return RandomizableWeights<T>.EmptyWeights;
|
|
case JsonTokenType.String:
|
|
case JsonTokenType.Number:
|
|
var value = valueConverter.Read(ref reader, this.valueType, options);
|
|
return RandomizableWeights<T>.ConstantWeights(value);
|
|
case JsonTokenType.StartObject:
|
|
var dict = dictionaryConverter.Read(ref reader, this.dictionaryType, options);
|
|
if (dict == null) {
|
|
return RandomizableWeights<T>.EmptyWeights;
|
|
} else {
|
|
return RandomizableWeights<T>.FromDictionary(dict);
|
|
}
|
|
default:
|
|
throw new JsonException();
|
|
}
|
|
}
|
|
|
|
public override void Write(Utf8JsonWriter writer, RandomizableWeights<T> value, JsonSerializerOptions options) {
|
|
switch (value.Options.Count) {
|
|
case 0:
|
|
writer.WriteNullValue();
|
|
break;
|
|
case 1:
|
|
this.valueConverter.Write(writer, value.Options[0].Item, options);
|
|
break;
|
|
default:
|
|
writer.WriteStartObject();
|
|
foreach (var (item, weight) in value.Options) {
|
|
this.valueConverter.WriteAsPropertyName(writer, item, options);
|
|
writer.WriteNumberValue(weight);
|
|
}
|
|
writer.WriteEndObject();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|