55 lines
2.3 KiB
C#
55 lines
2.3 KiB
C#
using System.Text.Json;
|
|||
|
|
using System.Text.Json.Serialization;
|
||
|
|
|
||
|
|
namespace NucleicBroker;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// NDJSON JSON-RPC 2.0 plumbing (docs/WINDOWS_PORT.md §3.3): one JSON object per line,
|
||
|
|
/// requests flow hostd → broker only, notifications broker → hostd only. Binary payloads
|
||
|
|
/// ride base64 in `b64` fields.
|
||
|
|
/// </summary>
|
||
|
|
public static class Rpc
|
||
|
|
{
|
||
|
|
public static readonly JsonSerializerOptions Json = new()
|
||
|
|
{
|
||
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||
|
|
PropertyNameCaseInsensitive = true,
|
||
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||
|
|
};
|
||
|
|
|
||
|
|
/// <summary>A JSON `null`, used as the response id for unidentifiable requests — the
|
||
|
|
/// spec requires `"id": null` to be PRESENT, which the ignore-null policy would drop if
|
||
|
|
/// we passed a bare null.</summary>
|
||
|
|
private static readonly JsonElement NullId = JsonDocument.Parse("null").RootElement;
|
||
|
|
|
||
|
|
// JSON-RPC 2.0 error codes (+ -32000 for structured facade errors, kind in data).
|
||
|
|
public const int ParseError = -32700;
|
||
|
|
public const int InvalidRequest = -32600;
|
||
|
|
public const int MethodNotFound = -32601;
|
||
|
|
public const int InvalidParams = -32602;
|
||
|
|
public const int InternalError = -32603;
|
||
|
|
public const int FacadeError = -32000;
|
||
|
|
|
||
|
|
public static string Response(JsonElement id, object result) =>
|
||
|
|
JsonSerializer.Serialize(new { jsonrpc = "2.0", id, result }, Json);
|
||
|
|
|
||
|
|
public static string Error(JsonElement? id, int code, string message, object? data = null) =>
|
||
|
|
JsonSerializer.Serialize(
|
||
|
|
new { jsonrpc = "2.0", id = id ?? NullId, error = new { code, message, data } },
|
||
|
|
Json);
|
||
|
|
|
||
|
|
public static string Notification(string method, object @params) =>
|
||
|
|
JsonSerializer.Serialize(new { jsonrpc = "2.0", method, @params }, Json);
|
||
|
|
|
||
|
|
/// <summary>Deserialize a request's params object; throws JsonException on a missing or
|
||
|
|
/// mismatched shape (the dispatcher maps that to InvalidParams). Positional records bind
|
||
|
|
/// through their constructor, case-insensitively.</summary>
|
||
|
|
public static T Params<T>(JsonElement? @params)
|
||
|
|
{
|
||
|
|
if (@params is not { ValueKind: JsonValueKind.Object } p)
|
||
|
|
throw new JsonException("missing params object");
|
||
|
|
return JsonSerializer.Deserialize<T>(p.GetRawText(), Json)
|
||
|
|
?? throw new JsonException("params decoded to null");
|
||
|
|
}
|
||
|
|
}
|