System.Text.Json deserialization is incompatible with this usage
This commit is contained in:
parent
af6a02b6dc
commit
854b51b46b
3 changed files with 77 additions and 29 deletions
|
|
@ -1,21 +1,12 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace pdns_dhcp.PowerDns;
|
||||
|
||||
public interface IMethod;
|
||||
|
||||
[JsonPolymorphic(TypeDiscriminatorPropertyName = "method")]
|
||||
[JsonDerivedType(typeof(InitializeMethod), "initialize")]
|
||||
[JsonDerivedType(typeof(LookupMethod), "lookup")]
|
||||
public class Method;
|
||||
public record MethodBase(string Method);
|
||||
|
||||
public abstract class Method<TParam>(TParam parameters) : Method
|
||||
where TParam : MethodParameters
|
||||
{
|
||||
[JsonPropertyName("parameters")]
|
||||
public TParam Parameters => parameters;
|
||||
}
|
||||
public abstract record Method<TParam>(string Method, TParam Parameters) : MethodBase(Method)
|
||||
where TParam : MethodParameters;
|
||||
|
||||
public class InitializeMethod(InitializeParameters parameters) : Method<InitializeParameters>(parameters), IMethod;
|
||||
public record InitializeMethod(InitializeParameters Parameters) : Method<InitializeParameters>("initialize", Parameters), IMethod;
|
||||
|
||||
public class LookupMethod(LookupParameters parameters) : Method<LookupParameters>(parameters), IMethod;
|
||||
public record LookupMethod(LookupParameters Parameters) : Method<LookupParameters>("lookup", Parameters), IMethod;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Buffers;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net.Sockets;
|
||||
using System.Text.Json;
|
||||
|
|
@ -15,9 +16,34 @@ namespace pdns_dhcp.PowerDns;
|
|||
|
||||
public class PowerDnsHandler : ConnectionHandler
|
||||
{
|
||||
delegate MethodBase? HandlerConverter(in JsonElement element);
|
||||
|
||||
private static readonly ReadOnlyDictionary<string, HandlerConverter> Converters;
|
||||
|
||||
private readonly ILogger<PowerDnsHandler> _logger;
|
||||
private readonly DnsRepository _repository;
|
||||
|
||||
static PowerDnsHandler()
|
||||
{
|
||||
Dictionary<string, HandlerConverter> converters = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["initialize"] = ToInitialize,
|
||||
["lookup"] = ToLookup
|
||||
};
|
||||
|
||||
Converters = converters.AsReadOnly();
|
||||
|
||||
static InitializeMethod ToInitialize(in JsonElement element)
|
||||
{
|
||||
return new(element.Deserialize(PowerDnsSerializerContext.Default.InitializeParameters)!);
|
||||
}
|
||||
|
||||
static LookupMethod ToLookup(in JsonElement element)
|
||||
{
|
||||
return new(element.Deserialize(PowerDnsSerializerContext.Default.LookupParameters)!);
|
||||
}
|
||||
}
|
||||
|
||||
public PowerDnsHandler(DnsRepository repository, ILogger<PowerDnsHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
|
|
@ -41,11 +67,33 @@ public class PowerDnsHandler : ConnectionHandler
|
|||
foreach (var memory in read.Buffer)
|
||||
{
|
||||
buffer.Write(memory.Span);
|
||||
if (ConsumeJson(buffer, json, ref state))
|
||||
if (!ConsumeJson(buffer, json, ref state))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
MethodBase method;
|
||||
try
|
||||
{
|
||||
using var jsonDocument = JsonDocument.Parse(json.WrittenMemory);
|
||||
var root = jsonDocument.RootElement;
|
||||
if (!root.TryGetProperty("method", out var methodElement))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Parse(methodElement, root.GetProperty("parameters")) is not { } methodLocal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
method = methodLocal;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var method = JsonSerializer.Deserialize(json.WrittenSpan, PowerDnsSerializerContext.Default.Method)!;
|
||||
json.Clear();
|
||||
state = default;
|
||||
}
|
||||
|
||||
Reply reply = BoolReply.False;
|
||||
try
|
||||
|
|
@ -57,7 +105,6 @@ public class PowerDnsHandler : ConnectionHandler
|
|||
await JsonSerializer.SerializeAsync(writer, reply, PowerDnsSerializerContext.Default.Reply, connection.ConnectionClosed)
|
||||
.ConfigureAwait(continueOnCapturedContext: false);
|
||||
}
|
||||
}
|
||||
|
||||
input.AdvanceTo(read.Buffer.End);
|
||||
}
|
||||
|
|
@ -111,9 +158,20 @@ public class PowerDnsHandler : ConnectionHandler
|
|||
|
||||
return final;
|
||||
}
|
||||
|
||||
static MethodBase? Parse(in JsonElement element, in JsonElement parameters)
|
||||
{
|
||||
HandlerConverter? converter = default;
|
||||
return element.GetString() switch
|
||||
{
|
||||
null => null,
|
||||
{ } methodName when !Converters.TryGetValue(methodName, out converter) => new MethodBase(methodName),
|
||||
_ => converter(parameters)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private ValueTask<Reply> Handle(Method method, CancellationToken cancellationToken = default)
|
||||
private ValueTask<Reply> Handle(MethodBase method, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return method switch
|
||||
{
|
||||
|
|
@ -123,7 +181,7 @@ public class PowerDnsHandler : ConnectionHandler
|
|||
_ => LogUnhandled(_logger, method)
|
||||
};
|
||||
|
||||
static ValueTask<Reply> LogUnhandled(ILogger logger, Method method)
|
||||
static ValueTask<Reply> LogUnhandled(ILogger logger, MethodBase method)
|
||||
{
|
||||
logger.LogWarning("Unhandled Method {Method}", method);
|
||||
return ValueTask.FromResult<Reply>(BoolReply.False);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ using System.Text.Json.Serialization;
|
|||
namespace pdns_dhcp.PowerDns;
|
||||
|
||||
[JsonSerializable(typeof(Reply))]
|
||||
[JsonSerializable(typeof(Method))]
|
||||
[JsonSerializable(typeof(Parameters))]
|
||||
[JsonSourceGenerationOptions(
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue