Appearance
| 1 | namespace Analysis.Protocol is | |
| 2 | use System.Text.Json.JsonSerializer | |
| 3 | use System.Text.Json.JsonSerializerOptions | |
| 4 | ||
| 5 | // Wire helper for the JSON analysis protocol. One JSON object per line, | |
| 6 | // newline-terminated; a message never contains a raw newline (JSON escapes | |
| 7 | // them inside strings), so `read_line` is a complete framing primitive. | |
| 8 | // | |
| 9 | // Requests deserialize into the REQUEST discriminated union (by the | |
| 10 | // `command` field); responses serialize from the RESPONSE union (tagged | |
| 11 | // with `kind`). Wire field names are the ghūl property names verbatim | |
| 12 | // (snake_case); no `JsonNamingPolicy` is applied. | |
| 13 | class JSON_PROTOCOL is | |
| 14 | _options: JsonSerializerOptions? static | |
| 15 | ||
| 16 | options: JsonSerializerOptions static is | |
| 17 | let options mut = _options | |
| 18 | ||
| 19 | if !options? then | |
| 20 | options = JSON_OPTIONS.create() | |
| 21 | ||
| 22 | _options = options | |
| 23 | fi | |
| 24 | ||
| 25 | return options | |
| 26 | si | |
| 27 | ||
| 28 | // Deserialize one request line. A malformed line throws out of | |
| 29 | // JsonSerializer; the reader thread catches it and queues a | |
| 30 | // PARSE_ERROR frame, which the despatcher answers with an error | |
| 31 | // response. | |
| 32 | deserialize_request(line: string) -> Request? static => | |
| 33 | JsonSerializer.deserialize[Request](line, options) | |
| 34 | ||
| 35 | // Serialize a response onto a single line and flush. Every response | |
| 36 | // frame is one line; the client splits stdout on '\n'. | |
| 37 | write_response(writer: IO.TextWriter, response: Response) static is | |
| 38 | writer.write(JsonSerializer.serialize[Response](response, options)) | |
| 39 | writer.write("\n") | |
| 40 | writer.flush() | |
| 41 | si | |
| 42 | si | |
| 43 | si |