You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
recyclarr/src/Trash/YamlDotNet/YamlNullableEnumTypeConvert...

74 lines
2.3 KiB

using System;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
namespace Trash.YamlDotNet
{
// A workaround for nullable enums in YamlDotNet taken from:
// https://github.com/aaubry/YamlDotNet/issues/544#issuecomment-778062351
internal class YamlNullableEnumTypeConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
return Nullable.GetUnderlyingType(type)?.IsEnum ?? false;
}
public object? ReadYaml(IParser parser, Type type)
{
type = Nullable.GetUnderlyingType(type) ??
throw new ArgumentException("Expected nullable enum type for ReadYaml");
if (parser.Accept<NodeEvent>(out var @event))
{
if (NodeIsNull(@event))
{
parser.SkipThisAndNestedEvents();
return null;
}
}
var scalar = parser.Consume<Scalar>();
try
{
return Enum.Parse(type, scalar.Value, true);
}
catch (Exception ex)
{
throw new Exception($"Invalid value: \"{scalar.Value}\" for {type.Name}", ex);
}
}
public void WriteYaml(IEmitter emitter, object? value, Type type)
{
type = Nullable.GetUnderlyingType(type) ??
throw new ArgumentException("Expected nullable enum type for WriteYaml");
if (value != null)
{
var toWrite = Enum.GetName(type, value) ??
throw new InvalidOperationException($"Invalid value {value} for enum: {type}");
emitter.Emit(new Scalar(null!, null!, toWrite, ScalarStyle.Any, true, false));
}
}
private static bool NodeIsNull(NodeEvent nodeEvent)
{
// http://yaml.org/type/null.html
if (nodeEvent.Tag == "tag:yaml.org,2002:null")
{
return true;
}
if (nodeEvent is Scalar scalar && scalar.Style == ScalarStyle.Plain)
{
var value = scalar.Value;
return value is "" or "~" or "null" or "Null" or "NULL";
}
return false;
}
}
}