Skip to content

Commit 7c58e53

Browse files
committed
cdp: refacto message JSON read
1 parent 826f826 commit 7c58e53

File tree

11 files changed

+424
-401
lines changed

11 files changed

+424
-401
lines changed

src/cdp/browser.zig

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const server = @import("../server.zig");
2222
const Ctx = server.Ctx;
2323
const cdp = @import("cdp.zig");
2424
const result = cdp.result;
25-
const getMsg = cdp.getMsg;
25+
const IncomingMessage = @import("msg.zig").IncomingMessage;
2626

2727
const log = std.log.scoped(.cdp);
2828

@@ -35,18 +35,17 @@ const Methods = enum {
3535

3636
pub fn browser(
3737
alloc: std.mem.Allocator,
38-
id: ?u16,
38+
msg: *IncomingMessage,
3939
action: []const u8,
40-
scanner: *std.json.Scanner,
4140
ctx: *Ctx,
4241
) ![]const u8 {
4342
const method = std.meta.stringToEnum(Methods, action) orelse
4443
return error.UnknownMethod;
4544
return switch (method) {
46-
.getVersion => getVersion(alloc, id, scanner, ctx),
47-
.setDownloadBehavior => setDownloadBehavior(alloc, id, scanner, ctx),
48-
.getWindowForTarget => getWindowForTarget(alloc, id, scanner, ctx),
49-
.setWindowBounds => setWindowBounds(alloc, id, scanner, ctx),
45+
.getVersion => getVersion(alloc, msg, ctx),
46+
.setDownloadBehavior => setDownloadBehavior(alloc, msg, ctx),
47+
.getWindowForTarget => getWindowForTarget(alloc, msg, ctx),
48+
.setWindowBounds => setWindowBounds(alloc, msg, ctx),
5049
};
5150
}
5251

@@ -59,14 +58,12 @@ const JsVersion = "12.4.254.8";
5958

6059
fn getVersion(
6160
alloc: std.mem.Allocator,
62-
_id: ?u16,
63-
scanner: *std.json.Scanner,
61+
msg: *IncomingMessage,
6462
_: *Ctx,
6563
) ![]const u8 {
66-
6764
// input
68-
const msg = try getMsg(alloc, _id, void, scanner);
69-
log.debug("Req > id {d}, method {s}", .{ msg.id, "browser.getVersion" });
65+
const input = try msg.getInput(alloc, void);
66+
log.debug("Req > id {d}, method {s}", .{ input.id, "browser.getVersion" });
7067

7168
// ouput
7269
const Res = struct {
@@ -76,48 +73,45 @@ fn getVersion(
7673
userAgent: []const u8 = UserAgent,
7774
jsVersion: []const u8 = JsVersion,
7875
};
79-
return result(alloc, msg.id, Res, .{}, null);
76+
return result(alloc, input.id, Res, .{}, null);
8077
}
8178

8279
// TODO: noop method
8380
fn setDownloadBehavior(
8481
alloc: std.mem.Allocator,
85-
_id: ?u16,
86-
scanner: *std.json.Scanner,
82+
msg: *IncomingMessage,
8783
_: *Ctx,
8884
) ![]const u8 {
89-
9085
// input
9186
const Params = struct {
9287
behavior: []const u8,
9388
browserContextId: ?[]const u8 = null,
9489
downloadPath: ?[]const u8 = null,
9590
eventsEnabled: ?bool = null,
9691
};
97-
const msg = try getMsg(alloc, _id, Params, scanner);
98-
log.debug("REQ > id {d}, method {s}", .{ msg.id, "browser.setDownloadBehavior" });
92+
const input = try msg.getInput(alloc, Params);
93+
log.debug("REQ > id {d}, method {s}", .{ input.id, "browser.setDownloadBehavior" });
9994

10095
// output
101-
return result(alloc, msg.id, null, null, null);
96+
return result(alloc, input.id, null, null, null);
10297
}
10398

10499
// TODO: hard coded ID
105100
const DevToolsWindowID = 1923710101;
106101

107102
fn getWindowForTarget(
108103
alloc: std.mem.Allocator,
109-
_id: ?u16,
110-
scanner: *std.json.Scanner,
104+
msg: *IncomingMessage,
111105
_: *Ctx,
112106
) ![]const u8 {
113107

114108
// input
115109
const Params = struct {
116110
targetId: ?[]const u8 = null,
117111
};
118-
const msg = try cdp.getMsg(alloc, _id, ?Params, scanner);
119-
std.debug.assert(msg.sessionID != null);
120-
log.debug("Req > id {d}, method {s}", .{ msg.id, "browser.getWindowForTarget" });
112+
const input = try msg.getInput(alloc, Params);
113+
std.debug.assert(input.sessionId != null);
114+
log.debug("Req > id {d}, method {s}", .{ input.id, "browser.getWindowForTarget" });
121115

122116
// output
123117
const Resp = struct {
@@ -130,21 +124,20 @@ fn getWindowForTarget(
130124
windowState: []const u8 = "normal",
131125
} = .{},
132126
};
133-
return result(alloc, msg.id, Resp, Resp{}, msg.sessionID.?);
127+
return result(alloc, input.id, Resp, Resp{}, input.sessionId);
134128
}
135129

136130
// TODO: noop method
137131
fn setWindowBounds(
138132
alloc: std.mem.Allocator,
139-
_id: ?u16,
140-
scanner: *std.json.Scanner,
133+
msg: *IncomingMessage,
141134
_: *Ctx,
142135
) ![]const u8 {
136+
const input = try msg.getInput(alloc, void);
143137

144138
// input
145-
const msg = try cdp.getMsg(alloc, _id, void, scanner);
146-
log.debug("Req > id {d}, method {s}", .{ msg.id, "browser.setWindowBounds" });
139+
log.debug("Req > id {d}, method {s}", .{ input.id, "browser.setWindowBounds" });
147140

148141
// output
149-
return result(alloc, msg.id, null, null, msg.sessionID);
142+
return result(alloc, input.id, null, null, input.sessionId);
150143
}

src/cdp/cdp.zig

Lines changed: 15 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const network = @import("network.zig").network;
3030
const emulation = @import("emulation.zig").emulation;
3131
const fetch = @import("fetch.zig").fetch;
3232
const performance = @import("performance.zig").performance;
33+
const IncomingMessage = @import("msg.zig").IncomingMessage;
3334

3435
const log_cdp = std.log.scoped(.cdp);
3536

@@ -70,51 +71,29 @@ pub fn do(
7071
ctx: *Ctx,
7172
) ![]const u8 {
7273

73-
// JSON scanner
74-
var scanner = std.json.Scanner.initCompleteInput(alloc, s);
75-
defer scanner.deinit();
74+
// incoming message parser
75+
var msg = IncomingMessage.init(alloc, s);
76+
defer msg.deinit();
7677

77-
std.debug.assert(try scanner.next() == .object_begin);
78-
79-
// handle 2 possible orders:
80-
// - id, method <...>
81-
// - method, id <...>
82-
var method_key = try nextString(&scanner);
83-
var method_token: std.json.Token = undefined;
84-
var id: ?u16 = null;
85-
// check swap order
86-
if (std.mem.eql(u8, method_key, "id")) {
87-
id = try getId(&scanner, method_key);
88-
method_key = try nextString(&scanner);
89-
method_token = try scanner.next();
90-
} else {
91-
method_token = try scanner.next();
92-
}
93-
try checkKey(method_key, "method");
94-
95-
// retrieve method
96-
if (method_token != .string) {
97-
return error.WrongTokenType;
98-
}
99-
const method_name = method_token.string;
78+
const method = try msg.getMethod();
10079

10180
// retrieve domain from method
102-
var iter = std.mem.splitScalar(u8, method_name, '.');
81+
var iter = std.mem.splitScalar(u8, method, '.');
10382
const domain = std.meta.stringToEnum(Domains, iter.first()) orelse
10483
return error.UnknonwDomain;
10584

10685
// select corresponding domain
10786
const action = iter.next() orelse return error.BadMethod;
10887
return switch (domain) {
109-
.Browser => browser(alloc, id, action, &scanner, ctx),
110-
.Target => target(alloc, id, action, &scanner, ctx),
111-
.Page => page(alloc, id, action, &scanner, ctx),
112-
.Log => log(alloc, id, action, &scanner, ctx),
113-
.Runtime => runtime(alloc, id, action, &scanner, s, ctx),
114-
.Network => network(alloc, id, action, &scanner, ctx),
115-
.Emulation => emulation(alloc, id, action, &scanner, ctx),
116-
.Fetch => fetch(alloc, id, action, &scanner, ctx),
117-
.Performance => performance(alloc, id, action, &scanner, ctx),
88+
.Browser => browser(alloc, &msg, action, ctx),
89+
.Target => target(alloc, &msg, action, ctx),
90+
.Page => page(alloc, &msg, action, ctx),
91+
.Log => log(alloc, &msg, action, ctx),
92+
.Runtime => runtime(alloc, &msg, action, ctx),
93+
.Network => network(alloc, &msg, action, ctx),
94+
.Emulation => emulation(alloc, &msg, action, ctx),
95+
.Fetch => fetch(alloc, &msg, action, ctx),
96+
.Performance => performance(alloc, &msg, action, ctx),
11897
};
11998
}
12099

@@ -133,14 +112,6 @@ pub const State = struct {
133112
// Utils
134113
// -----
135114

136-
fn nextString(scanner: *std.json.Scanner) ![]const u8 {
137-
const token = try scanner.next();
138-
if (token != .string) {
139-
return error.WrongTokenType;
140-
}
141-
return token.string;
142-
}
143-
144115
pub fn dumpFile(
145116
alloc: std.mem.Allocator,
146117
id: u16,
@@ -158,10 +129,6 @@ pub fn dumpFile(
158129
defer alloc.free(p);
159130
}
160131

161-
fn checkKey(key: []const u8, token: []const u8) !void {
162-
if (!std.mem.eql(u8, key, token)) return error.WrongToken;
163-
}
164-
165132
// caller owns the slice returned
166133
pub fn stringify(alloc: std.mem.Allocator, res: anytype) ![]const u8 {
167134
var out = std.ArrayList(u8).init(alloc);
@@ -230,97 +197,6 @@ pub fn sendEvent(
230197
try server.sendSync(ctx, event_msg);
231198
}
232199

233-
fn getParams(
234-
alloc: std.mem.Allocator,
235-
comptime T: type,
236-
scanner: *std.json.Scanner,
237-
key: []const u8,
238-
) !?T {
239-
240-
// check key is "params"
241-
if (!std.mem.eql(u8, "params", key)) return null;
242-
243-
// skip "params" if not requested
244-
if (T == void) {
245-
var finished: usize = 0;
246-
while (true) {
247-
switch (try scanner.next()) {
248-
.object_begin => finished += 1,
249-
.object_end => finished -= 1,
250-
else => continue,
251-
}
252-
if (finished == 0) break;
253-
}
254-
return void{};
255-
}
256-
257-
// parse "params"
258-
const options = std.json.ParseOptions{
259-
.max_value_len = scanner.input.len,
260-
.allocate = .alloc_if_needed,
261-
};
262-
return try std.json.innerParse(T, alloc, scanner, options);
263-
}
264-
265-
fn getId(scanner: *std.json.Scanner, key: []const u8) !?u16 {
266-
267-
// check key is "id"
268-
if (!std.mem.eql(u8, "id", key)) return null;
269-
270-
// parse "id"
271-
return try std.fmt.parseUnsigned(u16, (try scanner.next()).number, 10);
272-
}
273-
274-
fn getSessionId(scanner: *std.json.Scanner, key: []const u8) !?[]const u8 {
275-
276-
// check key is "sessionId"
277-
if (!std.mem.eql(u8, "sessionId", key)) return null;
278-
279-
// parse "sessionId"
280-
return try nextString(scanner);
281-
}
282-
283-
pub fn getMsg(
284-
alloc: std.mem.Allocator,
285-
_id: ?u16,
286-
comptime params_T: type,
287-
scanner: *std.json.Scanner,
288-
) !struct { id: u16, params: ?params_T, sessionID: ?[]const u8 } {
289-
var id_msg: ?u16 = null;
290-
var params: ?params_T = null;
291-
var sessionID: ?[]const u8 = null;
292-
293-
var t: std.json.Token = undefined;
294-
295-
while (true) {
296-
t = try scanner.next();
297-
if (t == .object_end) break;
298-
if (t != .string) {
299-
return error.WrongTokenType;
300-
}
301-
if (_id == null and id_msg == null) {
302-
id_msg = try getId(scanner, t.string);
303-
if (id_msg != null) continue;
304-
}
305-
if (params == null) {
306-
params = try getParams(alloc, params_T, scanner, t.string);
307-
if (params != null) continue;
308-
}
309-
if (sessionID == null) {
310-
sessionID = try getSessionId(scanner, t.string);
311-
}
312-
}
313-
314-
// end
315-
t = try scanner.next();
316-
if (t != .end_of_document) return error.CDPMsgEnd;
317-
318-
// check id
319-
if (_id == null and id_msg == null) return error.RequestWithoutID;
320-
321-
return .{ .id = _id orelse id_msg.?, .params = params, .sessionID = sessionID };
322-
}
323-
324200
// Common
325201
// ------
326202

0 commit comments

Comments
 (0)