diff --git a/src/spec_tests/ssz_static/root.zig b/src/spec_tests/ssz_static/root.zig index ec57b0b..b5f12ce 100644 --- a/src/spec_tests/ssz_static/root.zig +++ b/src/spec_tests/ssz_static/root.zig @@ -62,13 +62,13 @@ const CommonUnion = union { // AttestationData: types.AttestationData, // AttesterSlashing: types.AttesterSlashing, // BeaconBlock: types.BeaconBlock, - // BeaconBlockHeader: types.BeaconBlockHeader, + BeaconBlockHeader: types.BeaconBlockHeader, Checkpoint: types.Checkpoint, // Deposit: types.Deposit, - // DepositData: types.DepositData, - // DepositMessage: types.DepositMessage, - // Eth1Block: types.Eth1Block, - // Eth1Data: types.Eth1Data, + DepositData: types.DepositData, + DepositMessage: types.DepositMessage, + Eth1Block: types.Eth1Block, + Eth1Data: types.Eth1Data, Fork: types.Fork, ForkData: types.ForkData, // HistoricalBatch: types.HistoricalBatch, @@ -77,9 +77,9 @@ const CommonUnion = union { // ProposerSlashing: types.ProposerSlashing, // SignedBeaconBlock: types.SignedBeaconBlock, // SignedBeaconBlockHeader: types.SignedBeaconBlockHeader, - // SigningData: types.SigningData, + SigningData: types.SigningData, SyncAggregatorSelectionData: types.SyncAggregatorSelectionData, // only exist in altair or later - // Validator: types.Validator, + Validator: types.Validator, VoluntaryExit: types.VoluntaryExit, }; diff --git a/src/yaml/parse.zig b/src/yaml/parse.zig index fa711a4..a0a3c6e 100644 --- a/src/yaml/parse.zig +++ b/src/yaml/parse.zig @@ -1,7 +1,3 @@ -//! The code bellow is essentially a port of https://github.com/kubkon/zig-yaml -//! to the most recent version of zig with a couple of stylistic changes and support for -//! json yaml. - const std = @import("std"); const assert = std.debug.assert; const log = std.log.scoped(.parse); @@ -386,7 +382,8 @@ const Parser = struct { log.debug("(doc) begin {s}@{d}", .{ @tagName(self.tree.tokens[node.base.start].id), node.base.start }); // json format yaml - const is_one_line: bool = if (self.eatToken(.flow_map_start, &.{})) |doc_pos| is_one_line: { + + const is_json_format: bool = if (self.eatToken(.flow_map_start, &.{})) |doc_pos| is_one_line: { if (self.getCol(doc_pos) > 0) return error.MalformedYaml; if (self.eatToken(.tag, &.{ .new_line, .comment })) |_| { node.directive = try self.expectToken(.literal, &.{ .new_line, .comment }); @@ -394,8 +391,8 @@ const Parser = struct { break :is_one_line true; } else false; - if (is_one_line) { - return self.one_line_doc(node); + if (is_json_format) { + return self.handle_json_format(node); } // Parse header @@ -443,9 +440,9 @@ const Parser = struct { return &node.base; } - fn one_line_doc(self: *Parser, node: *Node.Doc) ParseError!*Node { + fn handle_json_format(self: *Parser, node: *Node.Doc) ParseError!*Node { // Parse value - node.value = try self.value(); + node.value = try self.json_format_map(); if (node.value == null) { self.token_it.seekBy(-1); } @@ -499,7 +496,6 @@ const Parser = struct { if (self.getCol(key_pos) < col) { break; } - const key = self.token_it.next() orelse return error.UnexpectedEof; switch (key.id) { .literal => {}, @@ -513,7 +509,88 @@ const Parser = struct { continue; }, } + log.debug("(map) key {s}@{d}", .{ self.tree.getRaw(key_pos, key_pos), key_pos }); + + // Separator + _ = try self.expectToken(.map_value_ind, &.{ .new_line, .comment }); + + // Parse value + const val = try self.value(); + errdefer if (val) |v| { + v.deinit(self.allocator); + }; + + if (val) |v| { + if (self.getCol(v.start) < self.getCol(key_pos)) { + return error.MalformedYaml; + } + if (v.cast(Node.Value)) |_| { + if (self.getCol(v.start) == self.getCol(key_pos)) { + return error.MalformedYaml; + } + } + } + + try node.values.append(self.allocator, .{ + .key = key_pos, + .value = val, + }); + } + + node.base.end = self.token_it.pos - 1; + + log.debug("(map) end {s}@{d}", .{ @tagName(self.tree.tokens[node.base.end].id), node.base.end }); + return &node.base; + } + + fn json_format_map(self: *Parser) ParseError!*Node { + const node = try self.allocator.create(Node.Map); + errdefer self.allocator.destroy(node); + node.* = .{}; + node.base.tree = self.tree; + node.base.start = self.token_it.pos; + errdefer { + for (node.values.items) |entry| { + if (entry.value) |val| { + val.deinit(self.allocator); + } + } + node.values.deinit(self.allocator); + } + + log.debug("(map) begin {s}@{d}", .{ @tagName(self.tree.tokens[node.base.start].id), node.base.start }); + + const col = self.getCol(node.base.start); + var currentNewLine = self.getLine(node.base.start); + + while (true) { + self.eatCommentsAndSpace(&.{}); + + // Parse key + const key_pos = self.token_it.pos; + if (self.getCol(key_pos) < col) { + // multiline cases, see validator.txt in test + const newLine = self.getLine(key_pos); + if (newLine > currentNewLine) { + currentNewLine = newLine; + } else { + break; + } + } + const key = self.token_it.next() orelse return error.UnexpectedEof; + switch (key.id) { + .literal => {}, + .doc_start, .doc_end, .eof => { + self.token_it.seekBy(-1); + break; + }, + else => { + // TODO key not being a literal + // return error.Unhandled; + continue; + }, + } log.debug("(map) key {s}@{d}", .{ self.tree.getRaw(key_pos, key_pos), key_pos }); // Separator diff --git a/src/yaml/yaml.zig b/src/yaml/yaml.zig index ffcfa77..7ad16d5 100644 --- a/src/yaml/yaml.zig +++ b/src/yaml/yaml.zig @@ -32,6 +32,7 @@ pub const Value = union(enum) { string: []const u8, list: List, map: Map, + bool: bool, pub fn asInt(self: Value) !i64 { if (self != .int) return error.TypeMismatch; @@ -53,6 +54,14 @@ pub const Value = union(enum) { return self.string; } + pub fn asBool(self: Value) !bool { + if (self != .string) return error.TypeMismatch; + const str = self.string; + if (std.mem.eql(u8, str, "true")) return true; + if (std.mem.eql(u8, str, "false")) return false; + return error.TypeMismatch; + } + pub fn asList(self: Value) !List { if (self == .list) { return self.list; @@ -97,6 +106,7 @@ pub const Value = union(enum) { .uint => |uint| return writer.print("{}", .{uint}), .float => |float| return writer.print("{d}", .{float}), .string => |string| return writer.print("{s}", .{string}), + .bool => |data| return writer.print("{any}", .{data}), .list => |list| { const len = list.len; if (len == 0) return; @@ -427,6 +437,7 @@ pub const Yaml = struct { }, .void => error.TypeMismatch, .optional => unreachable, + .bool => try value.asBool(), else => error.Unimplemented, }; }