Files
nucleic-windows/NucleicBroker/Rpc.cs
T

55 lines
2.3 KiB
C#
Raw Normal View History

2026-07-27 22:02:34 -07:00
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");
}
}