-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathdispatcher_hello.zig
More file actions
126 lines (106 loc) · 4.76 KB
/
dispatcher_hello.zig
File metadata and controls
126 lines (106 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Zig JR
// A Zig based JSON-RPC 2.0 library.
// Copyright (C) 2025 William W. Wong. All rights reserved.
// (williamw520@gmail.com)
//
// MIT License. See the LICENSE file.
//
const std = @import("std");
const Allocator = std.mem.Allocator;
const zigjr = @import("zigjr");
const RpcRequest = zigjr.RpcRequest;
const DispatchResult = zigjr.DispatchResult;
const ErrorCode = zigjr.ErrorCode;
pub fn main() !void {
var gpa = std.heap.DebugAllocator(.{}){};
defer _ = gpa.deinit();
const alloc = gpa.allocator();
var stdin_buffer: [1024]u8 = undefined;
var stdin_reader = std.fs.File.stdin().reader(&stdin_buffer);
const stdin = &stdin_reader.interface;
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;
// RequestDispatcher interface implemented by the custom dispatcher HelloDispatcher.
var hello_dispatcher = HelloDispatcher {};
const dispatcher = zigjr.RequestDispatcher.implBy(&hello_dispatcher);
// Construct a pipeline with the custom dispatcher.
var pipeline = try zigjr.RequestPipeline.init(alloc, dispatcher, null);
defer pipeline.deinit();
// Read request from stdin.
var read_buf = std.Io.Writer.Allocating.init(alloc);
defer read_buf.deinit();
const read_len = stdin.streamDelimiter(&read_buf.writer, '\n') catch |err| blk: {
switch (err) {
std.Io.Reader.StreamError.EndOfStream => break :blk read_buf.written().len,
else => return err,
}
};
if (read_len > 0) {
try stdout.print("Request: {s}\n", .{read_buf.written()});
// Run request through the pipeline.
const run_status = try pipeline.runRequest(read_buf.written());
if (run_status.hasReply()) {
try stdout.print("Response: {s}\n", .{pipeline.responseJson()});
} else {
try stdout.print("No response\n", .{});
}
try stdout.flush();
} else {
usage();
}
}
const HelloDispatcher = struct {
// The JSON-RPC request has been parsed into a RpcRequest. Dispatch on it here.
pub fn dispatch(_: @This(), dc: *zigjr.DispatchCtxImpl) !DispatchResult {
if (std.mem.eql(u8, dc.request.method, "hello")) {
// Result needs to be in JSON. Memory allocated from arena will be freed automatically.
const resultJson = try std.json.Stringify.valueAlloc(dc.arena, "Hello World", .{});
return DispatchResult.withResult(resultJson);
} else if (std.mem.eql(u8, dc.request.method, "hello-name")) {
if (dc.request.params == .array) {
const items = dc.request.params.array.items;
if (items.len > 0 and items[0] == .string) {
const result = try std.fmt.allocPrint(dc.arena, "Hello {s}", .{ items[0].string });
const resultJson = try std.json.Stringify.valueAlloc(dc.arena, result, .{});
return DispatchResult.withResult(resultJson);
}
}
return DispatchResult.withErr(ErrorCode.InvalidParams, "Invalid params.");
} else if (std.mem.eql(u8, dc.request.method, "hello-xtimes")) {
if (dc.request.params == .array) {
const items = dc.request.params.array.items;
if (items.len > 1 and items[0] == .string and items[1] == .integer) {
const result = try std.fmt.allocPrint(dc.arena, "Hello {s} X {} times",
.{ items[0].string, items[1].integer });
const resultJson = try std.json.Stringify.valueAlloc(dc.arena, result, .{});
return DispatchResult.withResult(resultJson);
}
}
return DispatchResult.withErr(ErrorCode.InvalidParams, "Invalid params.");
} else if (std.mem.eql(u8, dc.request.method, "say")) {
if (dc.request.params == .array) {
const items = dc.request.params.array.items;
if (items.len > 0 and items[0] == .string) {
std.debug.print("Say: {s}\n", .{items[0].string});
}
}
return DispatchResult.asNone();
} else {
return DispatchResult.withErr(ErrorCode.MethodNotFound, "Method not found.");
}
}
// The result has been processed; this call is the chance to clean up.
// After this call, the request and result in dc will be reset.
pub fn dispatchEnd(_: @This(), dc: *zigjr.DispatchCtxImpl) void {
_=dc;
}
};
fn usage() void {
std.debug.print(
\\Usage: dispatcher_hello
\\Usage: dispatcher_hello < message.json
\\
\\The program reads from stdin.
, .{});
}