diff --git a/src/cdp/browser.zig b/src/cdp/browser.zig index 56017ac4..12f882e2 100644 --- a/src/cdp/browser.zig +++ b/src/cdp/browser.zig @@ -112,7 +112,7 @@ fn getWindowForTarget( const Params = struct { targetId: ?[]const u8 = null, }; - const input = try Input(Params).get(alloc, msg); + const input = try Input(?Params).get(alloc, msg); defer input.deinit(); std.debug.assert(input.sessionId != null); log.debug("Req > id {d}, method {s}", .{ input.id, "browser.getWindowForTarget" }); diff --git a/src/cdp/msg.zig b/src/cdp/msg.zig index 960c4b9b..80532e35 100644 --- a/src/cdp/msg.zig +++ b/src/cdp/msg.zig @@ -146,7 +146,15 @@ pub const IncomingMessage = struct { return error.SkippedParams; } - try self.scanUntil("params"); + self.scanUntil("params") catch |err| { + // handle nullable type + if (@typeInfo(T) == .Optional) { + if (err == error.InvalidToken or err == error.EndOfDocument) { + return null; + } + } + return err; + }; // parse "params" const options = std.json.ParseOptions{ @@ -250,3 +258,34 @@ test "read incoming message with null session id" { try std.testing.expectEqual(1, try msg.getId()); } } + +test "message with nullable params" { + const T = struct { + bar: []const u8, + }; + + // nullable type, params is present => value + const not_null = + \\{"id": 1,"method":"foo","params":{"bar":"baz"}} + ; + var msg = IncomingMessage.init(std.testing.allocator, not_null); + defer msg.deinit(); + const input = try Input(?T).get(std.testing.allocator, &msg); + defer input.deinit(); + try std.testing.expectEqualStrings(input.params.?.bar, "baz"); + + // nullable type, params is not present => null + const is_null = + \\{"id": 1,"method":"foo","sessionId":"AAA"} + ; + var msg_null = IncomingMessage.init(std.testing.allocator, is_null); + defer msg_null.deinit(); + const input_null = try Input(?T).get(std.testing.allocator, &msg_null); + defer input_null.deinit(); + try std.testing.expectEqual(null, input_null.params); + try std.testing.expectEqualStrings("AAA", input_null.sessionId.?); + + // not nullable type, params is not present => error + const params_or_error = msg_null.getParams(std.testing.allocator, T); + try std.testing.expectError(error.EndOfDocument, params_or_error); +} diff --git a/src/cdp/target.zig b/src/cdp/target.zig index d038e2e8..5f63acdf 100644 --- a/src/cdp/target.zig +++ b/src/cdp/target.zig @@ -184,7 +184,7 @@ fn getTargetInfo( const Params = struct { targetId: ?[]const u8 = null, }; - const input = try Input(Params).get(alloc, msg); + const input = try Input(?Params).get(alloc, msg); defer input.deinit(); log.debug("Req > id {d}, method {s}", .{ input.id, "target.getTargetInfo" });