diff --git a/build.zig b/build.zig index c71aaf2..2da79e0 100644 --- a/build.zig +++ b/build.zig @@ -18,7 +18,9 @@ pub fn build(b: *std.Build) void { const run_cmd = b.addRunArtifact(exe); run_cmd.step.dependOn(b.getInstallStep()); - run_cmd.addPassthruArgs(); + if (b.args) |args| { + run_cmd.addArgs(args); + } const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); diff --git a/flake.lock b/flake.lock index caa78e7..bc7dbb5 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1791914995, - "narHash": "sha256-Zf/xfQEAasnwnmEfHqW/4hjDE/s44yn2hD4RuVIZRjA=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "b7a79d3fea1e214f6d668d521cecec0c01e26544", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1793110635, - "narHash": "sha256-dhoW6VgFWlaodSY5jrBn+CF2FLmaUvDVgM7+C7T2+NM=", + "lastModified": 1781577229, + "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=", "owner": "nixos", "repo": "nixpkgs", - "rev": "31ecbaca1bdefa45dffc409f0250bd8039ea0010", + "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f", "type": "github" }, "original": { diff --git a/src/Class.zig b/src/Class.zig index be8324b..09a3846 100644 --- a/src/Class.zig +++ b/src/Class.zig @@ -33,14 +33,12 @@ pub const ClassAccessFlags = EnumFlags(enum(u16) { module = 0x8000, }); -pub const ParseError = std.Io.Reader.Error || std.mem.Allocator.Error || error{ +pub const ParseError = std.Io.Reader.Error || std.mem.Allocator.Error || error { InvalidMagicNumber, InvalidTag, - InvalidOp, - InvalidArrayType, }; -pub const ResolveError = error{ +pub const ResolveError = error { InvalidConstantPoolIndex, InvalidConstantType, }; @@ -121,12 +119,8 @@ fn parseFields(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: st const fields = try allocator.alloc(FieldInfo, fields_count); errdefer allocator.free(fields); - var parsed: usize = 0; - errdefer for (0..parsed) |i| fields[i].deinit(allocator); - for (0..fields_count) |i| { - fields[i] = try .parse(input, constant_pool, allocator); - parsed += 1; + fields[i] = try FieldInfo.parse(input, constant_pool, allocator); } return fields; @@ -137,12 +131,8 @@ fn parseMethods(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: s const methods = try allocator.alloc(MethodInfo, methods_count); errdefer allocator.free(methods); - var parsed: usize = 0; - errdefer for (0..parsed) |i| methods[i].deinit(allocator); - for (0..methods_count) |i| { methods[i] = try .parse(input, constant_pool, allocator); - parsed += 1; } return methods; @@ -153,12 +143,8 @@ pub fn parseAttributes(input: *std.Io.Reader, constant_pool: ConstantPool, alloc const attributes = try allocator.alloc(AttributeInfo, attributes_count); errdefer allocator.free(attributes); - var parsed: usize = 0; - errdefer for (0..parsed) |i| attributes[i].deinit(allocator); - for (0..attributes_count) |i| { - attributes[i] = try .parse(input, constant_pool, allocator); - parsed += 1; + attributes[i] = try AttributeInfo.parse(input, constant_pool, allocator); } return attributes; @@ -166,34 +152,58 @@ pub fn parseAttributes(input: *std.Io.Reader, constant_pool: ConstantPool, alloc pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { self.constant_pool.deinit(allocator); + self.freeInterfaces(allocator); + self.freeFields(allocator); + self.freeMethods(allocator); + self.freeAttributes(allocator); +} +fn freeInterfaces(self: *Self, allocator: std.mem.Allocator) void { allocator.free(self.interfaces); +} +fn freeFields(self: *Self, allocator: std.mem.Allocator) void { for (self.fields) |*field_info| { field_info.deinit(allocator); } allocator.free(self.fields); +} +fn freeMethods(self: *Self, allocator: std.mem.Allocator) void { for (self.methods) |*method_info| { method_info.deinit(allocator); } allocator.free(self.methods); +} +fn freeAttributes(self: *Self, allocator: std.mem.Allocator) void { for (self.attributes) |*attr| { attr.deinit(allocator); } allocator.free(self.attributes); } +pub fn jsonStringify(self: *const Self, jws: *std.json.Stringify) !void { + try jws.beginObject(); + + inline for (std.meta.fields(Self)) |field| { + if (comptime std.mem.eql(u8, field.name, "allocator")) continue; + try jws.objectField(field.name); + try jws.write(@field(self, field.name)); + } + + try jws.endObject(); +} + pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { const depth = 2; var indent: u8 = 0; - try w.print("magic: 0x{X}\n", .{self.magic}); + try w.print("magic: 0x{X}\n", .{ self.magic }); try w.print("version: {d}.{d}\n", .{ self.major_version, self.minor_version }); - try w.print("flags: {f}\n", .{self.access_flags}); + try w.print("flags: {f}\n", .{ self.access_flags }); const this_class = self.thisClass() catch return error.WriteFailed; _ = try w.write("this class:\n"); @@ -212,7 +222,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { const info = self.constant_pool.getTag(interface, .class) catch return error.WriteFailed; try w.splatByteAll(' ', depth * indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, indent + 1, self.constant_pool); } @@ -222,7 +232,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { defer indent -= 1; try w.splatByteAll(' ', depth * indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try field.indentedFormat(w, depth, indent + 1, self.constant_pool); } @@ -232,7 +242,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { defer indent -= 1; try w.splatByteAll(' ', depth * indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try method.indentedFormat(w, depth, indent + 1, self.constant_pool); } @@ -242,7 +252,7 @@ pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { defer indent -= 1; try w.splatByteAll(' ', depth * indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try attribute.indentedFormat(w, depth, indent + 1, self.constant_pool); } } @@ -254,3 +264,4 @@ pub fn thisClass(self: *const Self) ResolveError!ConstantPool.Info { pub fn superClass(self: *const Self) ResolveError!?ConstantPool.Info { return self.constant_pool.getTagOptional(self.super_class, .class); } + diff --git a/src/Class/AttributeInfo.zig b/src/Class/AttributeInfo.zig index e8c2295..5fbdc9f 100644 --- a/src/Class/AttributeInfo.zig +++ b/src/Class/AttributeInfo.zig @@ -295,7 +295,7 @@ pub const AttributeInfo = union(enum) { _ = try w.write("predefined: yes\n"); try w.splatByteAll(' ', depth * indent); - try w.print("type: {t}\n", .{predefined}); + try w.print("type: {t}\n", .{ predefined }); switch (predefined) { .constant_value => |attr| { @@ -306,10 +306,10 @@ pub const AttributeInfo = union(enum) { }, .code => |attr| { try w.splatByteAll(' ', depth * indent); - try w.print("max_stack: {d}\n", .{attr.max_stack}); + try w.print("max_stack: {d}\n", .{ attr.max_stack }); try w.splatByteAll(' ', depth * indent); - try w.print("max_locals: {d}\n", .{attr.max_locals}); + try w.print("max_locals: {d}\n", .{ attr.max_locals }); try w.splatByteAll(' ', depth * indent); _ = try w.write("code:\n"); @@ -319,22 +319,20 @@ pub const AttributeInfo = union(enum) { defer instr_indent -= 1; try w.splatByteAll(' ', depth * instr_indent); - try w.print("{d}:\n", .{i}); - - try instr.indentedFormat(w, depth, instr_indent + 1, constant_pool); + try w.print("{d}: 0x{x}\n", .{ i, instr }); } try w.splatByteAll(' ', depth * indent); _ = try w.write("exception_table:\n"); var exception_indent = indent; for (attr.exception_table, 0..) |*exception, i| { - exception_indent += 1; - defer exception_indent -= 1; + exception_indent += 1; + defer exception_indent -= 1; - try w.splatByteAll(' ', depth * exception_indent); - try w.print("{d}:\n", .{i}); + try w.splatByteAll(' ', depth * exception_indent); + try w.print("{d}:\n", .{ i }); - try exception.indentedFormat(w, depth, exception_indent + 1, constant_pool); + try exception.indentedFormat(w, depth, exception_indent + 1, constant_pool); } try w.splatByteAll(' ', depth * indent); @@ -345,7 +343,7 @@ pub const AttributeInfo = union(enum) { defer attr_indent -= 1; try w.splatByteAll(' ', depth * attr_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try a.indentedFormat(w, depth, attr_indent + 1, constant_pool); } @@ -359,7 +357,7 @@ pub const AttributeInfo = union(enum) { defer stack_map_frame_indent -= 1; try w.splatByteAll(' ', depth * stack_map_frame_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try stack_map_frame.indentedFormat(w, depth, stack_map_frame_indent + 1, constant_pool); } @@ -375,7 +373,7 @@ pub const AttributeInfo = union(enum) { const info = constant_pool.getTag(exception_index, .class) catch return error.WriteFailed; try w.splatByteAll(' ', depth * exception_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, exception_indent + 1, constant_pool); } }, @@ -388,7 +386,7 @@ pub const AttributeInfo = union(enum) { defer class_indent -= 1; try w.splatByteAll(' ', depth * class_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try class.indentedFormat(w, depth, class_indent + 1, constant_pool); } }, @@ -420,7 +418,7 @@ pub const AttributeInfo = union(enum) { }, .source_debug_extension => |attr| { try w.splatByteAll(' ', depth * indent); - try w.print("debug_extension: {s}\n", .{attr.debug_extension}); + try w.print("debug_extension: {s}\n", .{ attr.debug_extension }); }, .line_number_table => |attr| { try w.splatByteAll(' ', depth * indent); @@ -431,7 +429,7 @@ pub const AttributeInfo = union(enum) { defer line_number_indent -= 1; try w.splatByteAll(' ', depth * line_number_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try line_number.indentedFormat(w, depth, line_number_indent + 1); } @@ -445,7 +443,7 @@ pub const AttributeInfo = union(enum) { defer local_variable_indent -= 1; try w.splatByteAll(' ', depth * local_variable_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try local_variable.indentedFormat(w, depth, local_variable_indent + 1, constant_pool); } @@ -459,7 +457,7 @@ pub const AttributeInfo = union(enum) { defer local_variable_type_indent -= 1; try w.splatByteAll(' ', depth * local_variable_type_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try local_variable_type.indentedFormat(w, depth, local_variable_type_indent + 1, constant_pool); } @@ -474,7 +472,7 @@ pub const AttributeInfo = union(enum) { defer annotation_indent -= 1; try w.splatByteAll(' ', depth * annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try annotation.indentedFormat(w, depth, annotation_indent + 1, constant_pool); } }, @@ -487,7 +485,7 @@ pub const AttributeInfo = union(enum) { defer annotation_indent -= 1; try w.splatByteAll(' ', depth * annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try annotation.indentedFormat(w, depth, annotation_indent + 1, constant_pool); } }, @@ -500,7 +498,7 @@ pub const AttributeInfo = union(enum) { defer parameter_annotation_indent -= 1; try w.splatByteAll(' ', depth * parameter_annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try parameter_annotation.indentedFormat(w, depth, parameter_annotation_indent + 1, constant_pool); } }, @@ -513,7 +511,7 @@ pub const AttributeInfo = union(enum) { defer parameter_annotation_indent -= 1; try w.splatByteAll(' ', depth * parameter_annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try parameter_annotation.indentedFormat(w, depth, parameter_annotation_indent + 1, constant_pool); } }, @@ -526,7 +524,7 @@ pub const AttributeInfo = union(enum) { defer type_annotation_indent -= 1; try w.splatByteAll(' ', depth * type_annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try type_annotation.indentedFormat(w, depth, type_annotation_indent + 1, constant_pool); } }, @@ -539,7 +537,7 @@ pub const AttributeInfo = union(enum) { defer type_annotation_indent -= 1; try w.splatByteAll(' ', depth * type_annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try type_annotation.indentedFormat(w, depth, type_annotation_indent + 1, constant_pool); } }, @@ -557,7 +555,7 @@ pub const AttributeInfo = union(enum) { defer bootstrap_method_indent -= 1; try w.splatByteAll(' ', depth * bootstrap_method_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try bootstrap_method.indentedFormat(w, depth, bootstrap_method_indent + 1, constant_pool); } }, @@ -570,7 +568,7 @@ pub const AttributeInfo = union(enum) { defer parameter_indent -= 1; try w.splatByteAll(' ', depth * parameter_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try parameter.indentedFormat(w, depth, parameter_indent + 1, constant_pool); } }, @@ -586,7 +584,7 @@ pub const AttributeInfo = union(enum) { const info = constant_pool.getTag(package_index, .package) catch return error.WriteFailed; try w.splatByteAll(' ', depth * package_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, package_indent + 1, constant_pool); } }, @@ -613,7 +611,7 @@ pub const AttributeInfo = union(enum) { const info = constant_pool.getTag(class_index, .class) catch return error.WriteFailed; try w.splatByteAll(' ', depth * class_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, class_indent + 1, constant_pool); } }, @@ -626,7 +624,7 @@ pub const AttributeInfo = union(enum) { defer component_indent -= 1; try w.splatByteAll(' ', depth * component_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try component.indentedFormat(w, depth, component_indent + 1, constant_pool); } }, @@ -641,7 +639,7 @@ pub const AttributeInfo = union(enum) { const info = constant_pool.getTag(class_index, .class) catch return error.WriteFailed; try w.splatByteAll(' ', depth * class_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, class_indent + 1, constant_pool); } }, @@ -692,14 +690,12 @@ pub const ConstantValue = struct { pub const Code = struct { max_stack: u16, max_locals: u16, - code: []Instruction, + code: []u8, exception_table: []ExceptionHandler, attributes: []AttributeInfo, const Self = @This(); - pub const Instruction = @import("Code/Instruction.zig").Instruction; - pub const ExceptionHandler = struct { start_pc: u16, end_pc: u16, @@ -714,13 +710,13 @@ pub const Code = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("start_pc: {d}\n", .{self.start_pc}); + try w.print("start_pc: {d}\n", .{ self.start_pc }); try w.splatByteAll(' ', depth * indent); - try w.print("end_pc: {d}\n", .{self.end_pc}); + try w.print("end_pc: {d}\n", .{ self.end_pc }); try w.splatByteAll(' ', depth * indent); - try w.print("handler_pc: {d}\n", .{self.handler_pc}); + try w.print("handler_pc: {d}\n", .{ self.handler_pc }); const catch_type = self.catchType(constant_pool) catch return error.WriteFailed; if (catch_type) |ct| { @@ -740,30 +736,12 @@ pub const Code = struct { const max_locals = try input.takeInt(u16, .big); const code_length = try input.takeInt(u32, .big); - var code_reader_buf: [1024]u8 = undefined; - var code_reader = input.limited(.limited(code_length), &code_reader_buf); - var code = &code_reader.interface; - var byte_index: usize = 0; - var instructions: std.ArrayList(Instruction) = .empty; - defer instructions.deinit(allocator); - - var parsed_instructions: usize = 0; - errdefer for (0..parsed_instructions) |i| instructions.items[i].deinit(allocator); - - loop: while (true) { - _ = code.peekByte() catch |err| switch (err) { - error.EndOfStream => break :loop, - else => return err, - }; - - try instructions.append(allocator, try .parse(code, allocator, &byte_index)); - parsed_instructions += 1; - } + const code = try input.readAlloc(allocator, code_length); + errdefer allocator.free(code); const exception_table_length = try input.takeInt(u16, .big); const exception_table = try allocator.alloc(ExceptionHandler, exception_table_length); errdefer allocator.free(exception_table); - for (exception_table) |*exception_handler| { exception_handler.* = .{ .start_pc = try input.takeInt(u16, .big), @@ -776,32 +754,22 @@ pub const Code = struct { const attribute_count = try input.takeInt(u16, .big); const attributes = try allocator.alloc(AttributeInfo, attribute_count); errdefer allocator.free(attributes); - - var parsed_attributes: usize = 0; - errdefer for (0..parsed_attributes) |i| attributes[i].deinit(allocator); - for (attributes) |*attribute| { attribute.* = try .parse(input, constant_pool, allocator); - parsed_attributes += 1; } return .{ .max_stack = max_stack, .max_locals = max_locals, - .code = try instructions.toOwnedSlice(allocator), + .code = code, .exception_table = exception_table, .attributes = attributes, }; } pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - for (self.code) |*instruction| { - instruction.deinit(allocator); - } allocator.free(self.code); - allocator.free(self.exception_table); - for (self.attributes) |*attr| { attr.deinit(allocator); } @@ -852,13 +820,13 @@ pub const StackMapTable = struct { 0...63 => .same_frame, 64...127 => .{ .same_locals_1_stack_item_frame = .{ - .stack = .{try .parse(input)}, + .stack = .{ try .parse(input) }, }, }, 247 => .{ .same_locals_1_stack_item_frame_extended = .{ .offset_delta = try input.takeInt(u16, .big), - .stack = .{try .parse(input)}, + .stack = .{ try .parse(input) }, }, }, 248...250 => .{ @@ -877,7 +845,6 @@ pub const StackMapTable = struct { const length = frame_type - 251; const locals = try allocator.alloc(StackMapTable.VerificationTypeInfo, length); errdefer allocator.free(locals); - for (locals) |*local| { local.* = try .parse(input); } @@ -895,7 +862,6 @@ pub const StackMapTable = struct { const number_of_locals = try input.takeInt(u16, .big); const locals = try allocator.alloc(StackMapTable.VerificationTypeInfo, number_of_locals); errdefer allocator.free(locals); - for (locals) |*local| { local.* = try .parse(input); } @@ -903,7 +869,6 @@ pub const StackMapTable = struct { const number_of_stack_items = try input.takeInt(u16, .big); const stack = try allocator.alloc(StackMapTable.VerificationTypeInfo, number_of_stack_items); errdefer allocator.free(stack); - for (stack) |*stack_item| { stack_item.* = try .parse(input); } @@ -939,7 +904,7 @@ pub const StackMapTable = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("frame_type: {s}\n", .{@tagName(self.*)}); + try w.print("frame_type: {s}\n", .{ @tagName(self.*) }); switch (self.*) { .same_locals_1_stack_item_frame => |same_locals_1_stack_item_frame| { @@ -951,14 +916,14 @@ pub const StackMapTable = struct { defer stack_indent -= 1; try w.splatByteAll(' ', depth * stack_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, stack_indent + 1, constant_pool); } }, .same_locals_1_stack_item_frame_extended => |same_locals_1_stack_item_frame_extended| { try w.splatByteAll(' ', depth * indent); - try w.print("offset_delta: {d}\n", .{same_locals_1_stack_item_frame_extended.offset_delta}); + try w.print("offset_delta: {d}\n", .{ same_locals_1_stack_item_frame_extended.offset_delta }); try w.splatByteAll(' ', depth * indent); _ = try w.write("stack:\n"); @@ -968,18 +933,18 @@ pub const StackMapTable = struct { defer stack_indent -= 1; try w.splatByteAll(' ', depth * stack_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, stack_indent + 1, constant_pool); } }, .chop_frame => |chop_frame| { try w.splatByteAll(' ', depth * indent); - try w.print("offset_delta: {d}\n", .{chop_frame.offset_delta}); + try w.print("offset_delta: {d}\n", .{ chop_frame.offset_delta }); }, .append_frame => |append_frame| { try w.splatByteAll(' ', depth * indent); - try w.print("offset_delta: {d}\n", .{append_frame.offset_delta}); + try w.print("offset_delta: {d}\n", .{ append_frame.offset_delta }); try w.splatByteAll(' ', depth * indent); _ = try w.write("locals:\n"); @@ -989,14 +954,14 @@ pub const StackMapTable = struct { defer locals_indent -= 1; try w.splatByteAll(' ', depth * locals_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, locals_indent + 1, constant_pool); } }, .full_frame => |full_frame| { try w.splatByteAll(' ', depth * indent); - try w.print("offset_delta: {d}\n", .{full_frame.offset_delta}); + try w.print("offset_delta: {d}\n", .{ full_frame.offset_delta }); try w.splatByteAll(' ', depth * indent); _ = try w.write("locals:\n"); @@ -1006,7 +971,7 @@ pub const StackMapTable = struct { defer locals_indent -= 1; try w.splatByteAll(' ', depth * locals_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, locals_indent + 1, constant_pool); } @@ -1019,7 +984,7 @@ pub const StackMapTable = struct { defer stack_indent -= 1; try w.splatByteAll(' ', depth * stack_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, stack_indent + 1, constant_pool); } @@ -1097,7 +1062,7 @@ pub const StackMapTable = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("tag: {s}\n", .{@tagName(self.*)}); + try w.print("tag: {s}\n", .{ @tagName(self.*) }); switch (self.*) { .object => |object| { @@ -1108,7 +1073,7 @@ pub const StackMapTable = struct { }, .uninitialized => |uninitialized| { try w.splatByteAll(' ', depth * indent); - try w.print("offset: {d}\n", .{uninitialized.offset}); + try w.print("offset: {d}\n", .{ uninitialized.offset }); }, else => {}, } @@ -1119,13 +1084,8 @@ pub const StackMapTable = struct { const number_of_entries = try input.takeInt(u16, .big); const entries = try allocator.alloc(StackMapTable.StackMapFrame, number_of_entries); errdefer allocator.free(entries); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| entries[i].deinit(allocator); - for (entries) |*entry| { entry.* = try .parse(input, allocator); - parsed += 1; } return .{ @@ -1150,7 +1110,6 @@ pub const Exceptions = struct { const number_of_exceptions = try input.takeInt(u16, .big); const exception_index_table = try allocator.alloc(u16, number_of_exceptions); errdefer allocator.free(exception_index_table); - for (exception_index_table) |*exception_index| { exception_index.* = try input.takeInt(u16, .big); } @@ -1197,7 +1156,7 @@ pub const InnerClasses = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.inner_class_access_flags}); + try w.print("flags: {f}\n", .{ self.inner_class_access_flags }); const inner_class = self.innerClass(constant_pool) catch return error.WriteFailed; try w.splatByteAll(' ', depth * indent); @@ -1236,7 +1195,6 @@ pub const InnerClasses = struct { const number_of_classes = try input.takeInt(u16, .big); const classes = try allocator.alloc(InnerClass, number_of_classes); errdefer allocator.free(classes); - for (classes) |*class| { class.* = .{ .inner_class_info_index = try input.takeInt(u16, .big), @@ -1278,7 +1236,7 @@ pub const EnclosingMethod = struct { } }; -pub const Synthetic = struct {}; +pub const Synthetic = struct { }; pub const Signature = struct { signature_index: u16, @@ -1344,10 +1302,10 @@ pub const LineNumberTable = struct { indent: u8, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("start_pc: {d}\n", .{self.start_pc}); + try w.print("start_pc: {d}\n", .{ self.start_pc }); try w.splatByteAll(' ', depth * indent); - try w.print("line_number: {d}\n", .{self.line_number}); + try w.print("line_number: {d}\n", .{ self.line_number }); } }; @@ -1355,7 +1313,6 @@ pub const LineNumberTable = struct { const line_number_table_length = try input.takeInt(u16, .big); const line_number_table = try allocator.alloc(LineNumber, line_number_table_length); errdefer allocator.free(line_number_table); - for (line_number_table) |*line_number| { line_number.* = .{ .start_pc = try input.takeInt(u16, .big), @@ -1393,10 +1350,10 @@ pub const LocalVariableTable = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("start_pc: {d}\n", .{self.start_pc}); + try w.print("start_pc: {d}\n", .{ self.start_pc }); try w.splatByteAll(' ', depth * indent); - try w.print("length: {d}\n", .{self.length}); + try w.print("length: {d}\n", .{ self.length }); const name_ = self.name(constant_pool) catch return error.WriteFailed; try w.splatByteAll(' ', depth * indent); @@ -1422,7 +1379,6 @@ pub const LocalVariableTable = struct { const local_variable_table_length = try input.takeInt(u16, .big); const local_variable_table = try allocator.alloc(LocalVariable, local_variable_table_length); errdefer allocator.free(local_variable_table); - for (local_variable_table) |*local_variable| { local_variable.* = .{ .start_pc = try input.takeInt(u16, .big), @@ -1463,10 +1419,10 @@ pub const LocalVariableTypeTable = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("start_pc: {d}\n", .{self.start_pc}); + try w.print("start_pc: {d}\n", .{ self.start_pc }); try w.splatByteAll(' ', depth * indent); - try w.print("length: {d}\n", .{self.length}); + try w.print("length: {d}\n", .{ self.length }); const name_ = self.name(constant_pool) catch return error.WriteFailed; try w.splatByteAll(' ', depth * indent); @@ -1492,7 +1448,6 @@ pub const LocalVariableTypeTable = struct { const local_variable_type_table_length = try input.takeInt(u16, .big); const local_variable_type_table = try allocator.alloc(LocalVariableType, local_variable_type_table_length); errdefer allocator.free(local_variable_type_table); - for (local_variable_type_table) |*local_variable_type| { local_variable_type.* = .{ .start_pc = try input.takeInt(u16, .big), @@ -1513,7 +1468,7 @@ pub const LocalVariableTypeTable = struct { } }; -pub const Deprecated = struct {}; +pub const Deprecated = struct { }; pub const ElementValue = union(enum) { // B, C, D, F, I, J, S, Z, s @@ -1530,7 +1485,7 @@ pub const ElementValue = union(enum) { }, pub const ConstValue = struct { - type: Type, + @"type": Type, index: u16, pub const Type = enum(u8) { @@ -1547,7 +1502,7 @@ pub const ElementValue = union(enum) { pub fn value(self: *const ConstValue, constant_pool: ConstantPool) ResolveError!ConstantPool.Info { const value_ = try constant_pool.get(self.index); - return switch (self.type) { + return switch (self.@"type") { .byte, .char, .int, .short, .boolean => blk: { if (!value_.is(.integer)) break :blk ResolveError.InvalidConstantType; break :blk value_; @@ -1598,7 +1553,7 @@ pub const ElementValue = union(enum) { return switch (tag) { 'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 's' => .{ .const_value = .{ - .type = @fromBackingInt(@intCast(tag)), + .@"type" = @enumFromInt(tag), .index = try input.takeInt(u16, .big), }, }, @@ -1621,13 +1576,8 @@ pub const ElementValue = union(enum) { const num_values = try input.takeInt(u16, .big); const values = try allocator.alloc(ElementValue, num_values); errdefer allocator.free(values); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| values[i].deinit(allocator); - for (values) |*value| { value.* = try .parse(input, allocator); - parsed += 1; } break :blk .{ @@ -1660,7 +1610,7 @@ pub const ElementValue = union(enum) { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("type: {s}\n", .{@tagName(self.*)}); + try w.print("type: {s}\n", .{ @tagName(self.*) }); switch (self.*) { .const_value => |const_value| { @@ -1699,7 +1649,7 @@ pub const ElementValue = union(enum) { defer value_indent -= 1; try w.splatByteAll(' ', depth * value_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try value.indentedFormat(w, depth, value_indent + 1, constant_pool); } @@ -1748,16 +1698,11 @@ pub const Annotation = struct { const num_element_value_pairs = try input.takeInt(u16, .big); const element_value_pairs = try allocator.alloc(ElementValuePair, num_element_value_pairs); errdefer allocator.free(element_value_pairs); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| element_value_pairs[i].value.deinit(allocator); - for (element_value_pairs) |*element_value_pair| { element_value_pair.* = .{ .element_name_index = try input.takeInt(u16, .big), .value = try .parse(input, allocator), }; - parsed += 1; } return .{ @@ -1780,7 +1725,7 @@ pub const Annotation = struct { indent: u8, constant_pool: ConstantPool, ) std.Io.Writer.Error!void { - const type_ = self.type(constant_pool) catch return error.WriteFailed; + const type_ = self.@"type"(constant_pool) catch return error.WriteFailed; try w.splatByteAll(' ', depth * indent); _ = try w.write("type:\n"); try type_.indentedFormat(w, depth, indent + 1, constant_pool); @@ -1793,7 +1738,7 @@ pub const Annotation = struct { defer element_value_pair_indent -= 1; try w.splatByteAll(' ', depth * element_value_pair_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try element_value_pair.indentedFormat(w, depth, element_value_pair_indent + 1, constant_pool); } } @@ -1812,13 +1757,8 @@ pub const RuntimeVisibleAnnotations = struct { const num_annotations = try input.takeInt(u16, .big); const annotations = try allocator.alloc(Annotation, num_annotations); errdefer allocator.free(annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| annotations[i].deinit(allocator); - for (annotations) |*annotation| { annotation.* = try .parse(input, allocator); - parsed += 1; } return .{ @@ -1843,13 +1783,8 @@ pub const RuntimeInvisibleAnnotations = struct { const num_annotations = try input.takeInt(u16, .big); const annotations = try allocator.alloc(Annotation, num_annotations); errdefer allocator.free(annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| annotations[i].deinit(allocator); - for (annotations) |*annotation| { annotation.* = try .parse(input, allocator); - parsed += 1; } return .{ @@ -1868,33 +1803,6 @@ pub const RuntimeInvisibleAnnotations = struct { pub const ParameterAnnotation = struct { annotations: []Annotation, - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self { - const num_annotations = try input.takeInt(u16, .big); - const annotations = try allocator.alloc(Annotation, num_annotations); - errdefer allocator.free(annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| annotations[i].deinit(allocator); - - for (annotations) |*annotation| { - annotation.* = try .parse(input, allocator); - parsed += 1; - } - - return .{ - .annotations = annotations, - }; - } - - pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - for (self.annotations) |*annotation| { - annotation.deinit(allocator); - } - allocator.free(self.annotations); - } - pub fn indentedFormat( self: *const ParameterAnnotation, w: *std.Io.Writer, @@ -1910,7 +1818,7 @@ pub const ParameterAnnotation = struct { defer annotation_indent -= 1; try w.splatByteAll(' ', depth * annotation_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try annotation.indentedFormat(w, depth, annotation_indent + 1, constant_pool); } } @@ -1925,13 +1833,17 @@ pub const RuntimeVisibleParameterAnnotations = struct { const num_parameters = try input.takeByte(); const parameter_annotations = try allocator.alloc(ParameterAnnotation, num_parameters); errdefer allocator.free(parameter_annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| parameter_annotations[i].deinit(allocator); - for (parameter_annotations) |*parameter_annotation| { - parameter_annotation.* = try .parse(input, allocator); - parsed += 1; + const num_annotations = try input.takeInt(u16, .big); + const annotations = try allocator.alloc(Annotation, num_annotations); + errdefer allocator.free(annotations); + for (annotations) |*annotation| { + annotation.* = try .parse(input, allocator); + } + + parameter_annotation.* = .{ + .annotations = annotations, + }; } return .{ @@ -1940,8 +1852,11 @@ pub const RuntimeVisibleParameterAnnotations = struct { } pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - for (self.parameter_annotations) |*parameter_annotation| { - parameter_annotation.deinit(allocator); + for (self.parameter_annotations) |parameter_annotation| { + for (parameter_annotation.annotations) |*annotation| { + annotation.deinit(allocator); + } + allocator.free(parameter_annotation.annotations); } allocator.free(self.parameter_annotations); } @@ -1956,13 +1871,17 @@ pub const RuntimeInvisibleParameterAnnotations = struct { const num_parameters = try input.takeByte(); const parameter_annotations = try allocator.alloc(ParameterAnnotation, num_parameters); errdefer allocator.free(parameter_annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| parameter_annotations[i].deinit(allocator); - for (parameter_annotations) |*parameter_annotation| { - parameter_annotation.* = try .parse(input, allocator); - parsed += 1; + const num_annotations = try input.takeInt(u16, .big); + const annotations = try allocator.alloc(Annotation, num_annotations); + errdefer allocator.free(annotations); + for (annotations) |*annotation| { + annotation.* = try .parse(input, allocator); + } + + parameter_annotation.* = .{ + .annotations = annotations, + }; } return .{ @@ -1971,8 +1890,11 @@ pub const RuntimeInvisibleParameterAnnotations = struct { } pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - for (self.parameter_annotations) |*parameter_annotation| { - parameter_annotation.deinit(allocator); + for (self.parameter_annotations) |parameter_annotation| { + for (parameter_annotation.annotations) |*annotation| { + annotation.deinit(allocator); + } + allocator.free(parameter_annotation.annotations); } allocator.free(self.parameter_annotations); } @@ -2061,7 +1983,7 @@ pub const TypeAnnotation = struct { bound_index: u8, }; - pub const Empty = struct {}; + pub const Empty = struct { }; pub const FormalParameter = struct { formal_parameter_index: u8, @@ -2086,13 +2008,13 @@ pub const TypeAnnotation = struct { indent: u8, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("start_pc: {d}\n", .{self.start_pc}); + try w.print("start_pc: {d}\n", .{ self.start_pc }); try w.splatByteAll(' ', depth * indent); - try w.print("length: {d}\n", .{self.length}); + try w.print("length: {d}\n", .{ self.length }); try w.splatByteAll(' ', depth * indent); - try w.print("start_pc: {d}\n", .{self.index}); + try w.print("start_pc: {d}\n", .{ self.index }); } }; }; @@ -2117,31 +2039,31 @@ pub const TypeAnnotation = struct { indent: u8, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("target_info_type: {t}\n", .{self.*}); + try w.print("target_info_type: {t}\n", .{ self.* }); switch (self.*) { .type_parameter => |*type_parameter| { try w.splatByteAll(' ', depth * indent); - try w.print("type_parameter_index: {d}\n", .{type_parameter.type_parameter_index}); + try w.print("type_parameter_index: {d}\n", .{ type_parameter.type_parameter_index }); }, .supertype => |*supertype| { try w.splatByteAll(' ', depth * indent); - try w.print("supertype_index: {d}\n", .{supertype.supertype_index}); + try w.print("supertype_index: {d}\n", .{ supertype.supertype_index }); }, .type_parameter_bound => |*type_parameter_bound| { try w.splatByteAll(' ', depth * indent); - try w.print("type_parameter_index: {d}\n", .{type_parameter_bound.type_parameter_index}); + try w.print("type_parameter_index: {d}\n", .{ type_parameter_bound.type_parameter_index }); try w.splatByteAll(' ', depth * indent); - try w.print("bound_index: {d}\n", .{type_parameter_bound.bound_index}); + try w.print("bound_index: {d}\n", .{ type_parameter_bound.bound_index }); }, .formal_parameter => |*formal_parameter| { try w.splatByteAll(' ', depth * indent); - try w.print("formal_parameter_index: {d}\n", .{formal_parameter.formal_parameter_index}); + try w.print("formal_parameter_index: {d}\n", .{ formal_parameter.formal_parameter_index }); }, .throws => |*throws| { try w.splatByteAll(' ', depth * indent); - try w.print("throws_type_index: {d}\n", .{throws.throws_type_index}); + try w.print("throws_type_index: {d}\n", .{ throws.throws_type_index }); }, .localvar => |*localvar| { try w.splatByteAll(' ', depth * indent); @@ -2152,25 +2074,25 @@ pub const TypeAnnotation = struct { defer entry_indent -= 1; try w.splatByteAll(' ', depth * entry_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try entry.indentedFormat(w, depth, indent); } }, .@"catch" => |*@"catch"| { try w.splatByteAll(' ', depth * indent); - try w.print("exception_table_index: {d}\n", .{@"catch".exception_table_index}); + try w.print("exception_table_index: {d}\n", .{ @"catch".exception_table_index }); }, .offset => |*offset| { try w.splatByteAll(' ', depth * indent); - try w.print("offset: {d}\n", .{offset.offset}); + try w.print("offset: {d}\n", .{ offset.offset }); }, .type_argument => |*type_argument| { try w.splatByteAll(' ', depth * indent); - try w.print("offset: {d}\n", .{type_argument.offset}); + try w.print("offset: {d}\n", .{ type_argument.offset }); try w.splatByteAll(' ', depth * indent); - try w.print("type_argument_index: {d}\n", .{type_argument.type_argument_index}); + try w.print("type_argument_index: {d}\n", .{ type_argument.type_argument_index }); }, else => {}, } @@ -2191,10 +2113,10 @@ pub const TypeAnnotation = struct { indent: u8, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("type_path_kind: {d}\n", .{self.type_path_kind}); + try w.print("type_path_kind: {d}\n", .{ self.type_path_kind }); try w.splatByteAll(' ', depth * indent); - try w.print("type_argument_index: {d}\n", .{self.type_argument_index}); + try w.print("type_argument_index: {d}\n", .{ self.type_argument_index }); } }; @@ -2202,7 +2124,6 @@ pub const TypeAnnotation = struct { const length = try input.takeByte(); const paths = try allocator.alloc(Path, length); errdefer allocator.free(paths); - for (paths) |*path| { path.* = .{ .type_path_kind = try input.takeByte(), @@ -2233,14 +2154,14 @@ pub const TypeAnnotation = struct { defer path_indent -= 1; try w.splatByteAll(' ', depth * path_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try path.indentedFormat(w, depth, path_indent + 1); } } }; pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self { - const target_type: TargetType = @fromBackingInt(@intCast(try input.takeInt(u8, .big))); + const target_type: TargetType = @enumFromInt(try input.takeInt(u8, .big)); const target_info: TargetInfo = switch (target_type) { .type_parameter_generic_class_interface, .type_parameter_generic_method_constructor => .{ .type_parameter = .{ @@ -2275,7 +2196,6 @@ pub const TypeAnnotation = struct { const table_length = try input.takeInt(u16, .big); const table = try allocator.alloc(TargetInfo.Localvar.Entry, table_length); errdefer allocator.free(table); - for (table) |*entry| { entry.* = .{ .start_pc = try input.takeInt(u16, .big), @@ -2291,7 +2211,7 @@ pub const TypeAnnotation = struct { }; }, .type_in_exception_parameter => .{ - .@"catch" = .{ + .@"catch" = . { .exception_table_index = try input.takeInt(u16, .big), }, }, @@ -2316,16 +2236,11 @@ pub const TypeAnnotation = struct { const num_element_value_pairs = try input.takeInt(u16, .big); const element_value_pairs = try allocator.alloc(ElementValuePair, num_element_value_pairs); errdefer allocator.free(element_value_pairs); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| element_value_pairs[i].value.deinit(allocator); - for (element_value_pairs) |*element_value_pair| { element_value_pair.* = .{ .element_name_index = try input.takeInt(u16, .big), .value = try .parse(input, allocator), }; - parsed += 1; } return .{ @@ -2342,7 +2257,6 @@ pub const TypeAnnotation = struct { .localvar => |localvar| allocator.free(localvar.table), else => {}, } - for (self.element_value_pairs) |*element_value_pair| { element_value_pair.value.deinit(allocator); } @@ -2357,7 +2271,7 @@ pub const TypeAnnotation = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("target_type: {t}\n", .{self.target_type}); + try w.print("target_type: {t}\n", .{ self.target_type }); try w.splatByteAll(' ', depth * indent); _ = try w.write("target_info:\n"); @@ -2367,7 +2281,7 @@ pub const TypeAnnotation = struct { _ = try w.write("target_path:\n"); try self.target_path.indentedFormat(w, depth + 1, indent); - const type_ = self.type(constant_pool) catch return error.WriteFailed; + const type_ = self.@"type"(constant_pool) catch return error.WriteFailed; try w.splatByteAll(' ', depth * indent); _ = try w.write("type:\n"); try type_.indentedFormat(w, depth, indent + 1, constant_pool); @@ -2380,7 +2294,7 @@ pub const TypeAnnotation = struct { defer element_value_pair_indent -= 1; try w.splatByteAll(' ', depth * element_value_pair_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try element_value_pair.indentedFormat(w, depth, element_value_pair_indent + 1, constant_pool); } } @@ -2399,13 +2313,8 @@ pub const RuntimeVisibleTypeAnnotations = struct { const num_annotations = try input.takeInt(u16, .big); const type_annotations = try allocator.alloc(TypeAnnotation, num_annotations); errdefer allocator.free(type_annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| type_annotations[i].deinit(allocator); - for (type_annotations) |*type_annotation| { type_annotation.* = try .parse(input, allocator); - parsed += 1; } return .{ @@ -2430,13 +2339,8 @@ pub const RuntimeInvisibleTypeAnnotations = struct { const num_annotations = try input.takeInt(u16, .big); const type_annotations = try allocator.alloc(TypeAnnotation, num_annotations); errdefer allocator.free(type_annotations); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| type_annotations[i].deinit(allocator); - for (type_annotations) |*type_annotation| { type_annotation.* = try .parse(input, allocator); - parsed += 1; } return .{ @@ -2499,7 +2403,7 @@ pub const BootstrapMethods = struct { const info = constant_pool.getLoadable(bootstrap_argument) catch return error.WriteFailed; try w.splatByteAll(' ', depth * bootstrap_argument_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, bootstrap_argument_indent + 1, constant_pool); } } @@ -2513,17 +2417,12 @@ pub const BootstrapMethods = struct { const num_bootstrap_methods = try input.takeInt(u16, .big); const bootstrap_methods = try allocator.alloc(BootstrapMethod, num_bootstrap_methods); errdefer allocator.free(bootstrap_methods); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| allocator.free(bootstrap_methods[i].bootstrap_arguments); - for (bootstrap_methods) |*bootstrap_method| { const bootstrap_method_ref = try input.takeInt(u16, .big); const num_bootstrap_arguments = try input.takeInt(u16, .big); const bootstrap_arguments = try allocator.alloc(u16, num_bootstrap_arguments); errdefer allocator.free(bootstrap_arguments); - for (bootstrap_arguments) |*bootstrap_argument| { bootstrap_argument.* = try input.takeInt(u16, .big); } @@ -2532,7 +2431,6 @@ pub const BootstrapMethods = struct { .bootstrap_method_ref = bootstrap_method_ref, .bootstrap_arguments = bootstrap_arguments, }; - parsed += 1; } return .{ @@ -2571,7 +2469,7 @@ pub const MethodParameters = struct { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.access_flags}); + try w.print("flags: {f}\n", .{ self.access_flags }); const name_ = self.name(constant_pool) catch return error.WriteFailed; if (name_) |n| { @@ -2590,7 +2488,6 @@ pub const MethodParameters = struct { const parameter_count = try input.takeByte(); const parameters = try allocator.alloc(Parameter, parameter_count); errdefer allocator.free(parameters); - for (parameters) |*parameter| { parameter.* = .{ .name_index = try input.takeInt(u16, .big), @@ -2651,7 +2548,7 @@ pub const Module = struct { try requires_.indentedFormat(w, depth, indent + 1, constant_pool); try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.requires_flags}); + try w.print("flags: {f}\n", .{ self.requires_flags }); const version = self.requiresVersion(constant_pool) catch return error.WriteFailed; if (version) |v| { @@ -2693,7 +2590,7 @@ pub const Module = struct { try exports_.indentedFormat(w, depth, indent + 1, constant_pool); try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.exports_flags}); + try w.print("flags: {f}\n", .{ self.exports_flags }); try w.splatByteAll(' ', depth * indent); _ = try w.write("exports_to:\n"); @@ -2705,7 +2602,7 @@ pub const Module = struct { const info = constant_pool.getTag(exports_to_index, .module) catch return error.WriteFailed; try w.splatByteAll(' ', depth * exports_to_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, exports_to_indent + 1, constant_pool); } } @@ -2738,7 +2635,7 @@ pub const Module = struct { try opens_.indentedFormat(w, depth, indent + 1, constant_pool); try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.opens_flags}); + try w.print("flags: {f}\n", .{ self.opens_flags }); try w.splatByteAll(' ', depth * indent); _ = try w.write("opens_to:\n"); @@ -2750,7 +2647,7 @@ pub const Module = struct { const info = constant_pool.getTag(opens_to_index, .module) catch return error.WriteFailed; try w.splatByteAll(' ', depth * opens_to_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, opens_to_indent + 1, constant_pool); } } @@ -2786,7 +2683,7 @@ pub const Module = struct { const info = constant_pool.getTag(provides_with_index, .class) catch return error.WriteFailed; try w.splatByteAll(' ', depth * provides_with_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, provides_with_indent + 1, constant_pool); } } @@ -2804,71 +2701,58 @@ pub const Module = struct { const requires_count = try input.takeInt(u16, .big); const requires = try allocator.alloc(Requires, requires_count); errdefer allocator.free(requires); - for (requires) |*r| { + const requires_index = try input.takeInt(u16, .big); + const requires_flags: Requires.RequiresFlags = .from(try input.takeInt(u16, .big)); + const requires_version_index = try input.takeInt(u16, .big); r.* = .{ - .requires_index = try input.takeInt(u16, .big), - .requires_flags = .from(try input.takeInt(u16, .big)), - .requires_version_index = try input.takeInt(u16, .big), + .requires_index = requires_index, + .requires_flags = requires_flags, + .requires_version_index = requires_version_index, }; } const exports_count = try input.takeInt(u16, .big); const exports = try allocator.alloc(Exports, exports_count); errdefer allocator.free(exports); - - var parsed_exports: usize = 0; - errdefer for (0..parsed_exports) |i| allocator.free(exports[i].exports_to_indeces); - for (exports) |*e| { const exports_index = try input.takeInt(u16, .big); const exports_flags: Exports.ExportsFlags = .from(try input.takeInt(u16, .big)); const exports_to_count = try input.takeInt(u16, .big); const exports_to_indeces = try allocator.alloc(u16, exports_to_count); errdefer allocator.free(exports_to_indeces); - for (exports_to_indeces) |*i| { i.* = try input.takeInt(u16, .big); } - e.* = .{ .exports_index = exports_index, .exports_flags = exports_flags, .exports_to_indeces = exports_to_indeces, }; - parsed_exports += 1; } const opens_count = try input.takeInt(u16, .big); const opens = try allocator.alloc(Opens, opens_count); errdefer allocator.free(opens); - - var parsed_opens: usize = 0; - errdefer for (0..parsed_opens) |i| allocator.free(opens[i].opens_to_indeces); - for (opens) |*o| { const opens_index = try input.takeInt(u16, .big); const opens_flags: Opens.OpensFlags = .from(try input.takeInt(u16, .big)); const opens_to_count = try input.takeInt(u16, .big); const opens_to_indeces = try allocator.alloc(u16, opens_to_count); errdefer allocator.free(opens_to_indeces); - for (opens_to_indeces) |*i| { i.* = try input.takeInt(u16, .big); } - o.* = .{ .opens_index = opens_index, .opens_flags = opens_flags, .opens_to_indeces = opens_to_indeces, }; - parsed_opens += 1; } const uses_count = try input.takeInt(u16, .big); const uses_indeces = try allocator.alloc(u16, uses_count); errdefer allocator.free(uses_indeces); - for (uses_indeces) |*i| { i.* = try input.takeInt(u16, .big); } @@ -2876,25 +2760,18 @@ pub const Module = struct { const provides_count = try input.takeInt(u16, .big); const provides = try allocator.alloc(Provides, provides_count); errdefer allocator.free(provides); - - var parsed_provides: usize = 0; - errdefer for (0..parsed_provides) |i| allocator.free(provides[i].provides_with_indeces); - for (provides) |*p| { const provides_index = try input.takeInt(u16, .big); const provides_with_count = try input.takeInt(u16, .big); const provides_with_indeces = try allocator.alloc(u16, provides_with_count); errdefer allocator.free(provides_with_indeces); - for (provides_with_indeces) |*i| { i.* = try input.takeInt(u16, .big); } - p.* = .{ .provides_index = provides_index, .provides_with_indeces = provides_with_indeces, }; - parsed_provides += 1; } return .{ @@ -2911,19 +2788,15 @@ pub const Module = struct { pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { allocator.free(self.requires); - for (self.exports) |*e| { allocator.free(e.exports_to_indeces); } allocator.free(self.exports); - for (self.opens) |*o| { allocator.free(o.opens_to_indeces); } allocator.free(self.opens); - allocator.free(self.uses_indeces); - for (self.provides) |*p| { allocator.free(p.provides_with_indeces); } @@ -2943,7 +2816,7 @@ pub const Module = struct { try module_name.indentedFormat(w, depth, indent + 1, constant_pool); try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.module_flags}); + try w.print("flags: {f}\n", .{ self.module_flags }); const module_version = self.moduleVersion(constant_pool) catch return error.WriteFailed; if (module_version) |m| { @@ -2960,7 +2833,7 @@ pub const Module = struct { defer requires_indent -= 1; try w.splatByteAll(' ', depth * requires_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try requires.indentedFormat(w, depth, requires_indent + 1, constant_pool); } @@ -2972,7 +2845,7 @@ pub const Module = struct { defer exports_indent -= 1; try w.splatByteAll(' ', depth * exports_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try exports.indentedFormat(w, depth, exports_indent + 1, constant_pool); } @@ -2984,7 +2857,7 @@ pub const Module = struct { defer opens_indent -= 1; try w.splatByteAll(' ', depth * opens_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try opens.indentedFormat(w, depth, opens_indent + 1, constant_pool); } @@ -2998,7 +2871,7 @@ pub const Module = struct { const info = constant_pool.getTag(uses_index, .class) catch return error.WriteFailed; try w.splatByteAll(' ', depth * uses_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try info.indentedFormat(w, depth, uses_indent + 1, constant_pool); } @@ -3010,7 +2883,7 @@ pub const Module = struct { defer provides_indent -= 1; try w.splatByteAll(' ', depth * provides_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try provides.indentedFormat(w, depth, provides_indent + 1, constant_pool); } } @@ -3033,7 +2906,6 @@ pub const ModulePackages = struct { const package_count = try input.takeInt(u16, .big); const package_indeces = try allocator.alloc(u16, package_count); errdefer allocator.free(package_indeces); - for (package_indeces) |*package_index| { package_index.* = try input.takeInt(u16, .big); } @@ -3088,7 +2960,6 @@ pub const NestMembers = struct { pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self { const number_of_classes = try input.takeInt(u16, .big); const classes = try allocator.alloc(u16, number_of_classes); - for (classes) |*class| { class.* = try input.takeInt(u16, .big); } @@ -3120,13 +2991,8 @@ pub const Record = struct { const attribute_count = try input.takeInt(u16, .big); const attributes = try allocator.alloc(AttributeInfo, attribute_count); errdefer allocator.free(attributes); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| attributes[i].deinit(allocator); - for (attributes) |*attribute| { attribute.* = try .parse(input, constant_pool, allocator); - parsed += 1; } return .{ @@ -3168,7 +3034,7 @@ pub const Record = struct { defer attr_indent -= 1; try w.splatByteAll(' ', depth * attr_indent); - try w.print("{d}:\n", .{i}); + try w.print("{d}:\n", .{ i }); try attr.indentedFormat(w, depth, attr_indent + 1, constant_pool); } } @@ -3185,13 +3051,8 @@ pub const Record = struct { pub fn parse(input: *std.Io.Reader, constant_pool: ConstantPool, allocator: std.mem.Allocator) (ParseError || ResolveError)!Self { const components_count = try input.takeInt(u16, .big); const components = try allocator.alloc(RecordComponentInfo, components_count); - - var parsed: usize = 0; - errdefer for (0..parsed) |i| components[i].deinit(allocator); - for (components) |*component| { component.* = try .parse(input, constant_pool, allocator); - parsed += 1; } return .{ @@ -3215,7 +3076,6 @@ pub const PermittedSubclasses = struct { pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self { const number_of_classes = try input.takeInt(u16, .big); const classes = try allocator.alloc(u16, number_of_classes); - for (classes) |*class| { class.* = try input.takeInt(u16, .big); } diff --git a/src/Class/Code/Instruction.zig b/src/Class/Code/Instruction.zig deleted file mode 100644 index 5d2b6f8..0000000 --- a/src/Class/Code/Instruction.zig +++ /dev/null @@ -1,1228 +0,0 @@ -const std = @import("std"); - -const Class = @import("../../Class.zig"); -const ConstantPool = Class.ConstantPool; -const ParseError = Class.ParseError; - -const Op = enum(u8) { - aaload = 0x32, - aastore = 0x53, - aconst_null = 0x1, - aload = 0x19, - aload_0 = 0x2a, - aload_1 = 0x2b, - aload_2 = 0x2c, - aload_3 = 0x2d, - anewarray = 0xbd, - areturn = 0xb0, - arraylength = 0xbe, - astore = 0x3a, - astore_0 = 0x4b, - astore_1 = 0x4c, - astore_2 = 0x4d, - astore_3 = 0x4e, - athrow = 0xbf, - baload = 0x33, - bastore = 0x54, - bipush = 0x10, - caload = 0x34, - castore = 0x55, - checkcast = 0xc0, - d2f = 0x90, - d2i = 0x8e, - d2l = 0x8f, - dadd = 0x63, - daload = 0x31, - dastore = 0x52, - dcmpg = 0x98, - dcmpl = 0x97, - dconst_0 = 0xe, - dconst_1 = 0xf, - ddiv = 0x6f, - dload = 0x18, - dload_0 = 0x26, - dload_1 = 0x27, - dload_2 = 0x28, - dload_3 = 0x29, - dmul = 0x6b, - dneg = 0x77, - drem = 0x73, - dreturn = 0xaf, - dstore = 0x39, - dstore_0 = 0x47, - dstore_1 = 0x48, - dstore_2 = 0x49, - dstore_3 = 0x4a, - dsub = 0x67, - dup = 0x59, - dup_x1 = 0x5a, - dup_x2 = 0x5b, - dup2 = 0x5c, - dup2_x1 = 0x5d, - dup2_x2 = 0x5e, - f2d = 0x8d, - f2i = 0x8b, - f2l = 0x8c, - fadd = 0x62, - faload = 0x30, - fastore = 0x51, - fcmpg = 0x96, - fcmpl = 0x95, - fconst_0 = 0xb, - fconst_1 = 0xc, - fconst_2 = 0xd, - fdiv = 0x6e, - fload = 0x17, - fload_0 = 0x22, - fload_1 = 0x23, - fload_2 = 0x24, - fload_3 = 0x25, - fmul = 0x6a, - fneg = 0x76, - frem = 0x72, - freturn = 0xae, - fstore = 0x38, - fstore_0 = 0x43, - fstore_1 = 0x44, - fstore_2 = 0x45, - fstore_3 = 0x46, - fsub = 0x66, - getfield = 0xb4, - getstatic = 0xb2, - goto = 0xa7, - goto_w = 0xc8, - i2b = 0x91, - i2c = 0x92, - i2d = 0x87, - i2f = 0x86, - i2l = 0x85, - i2s = 0x93, - iadd = 0x60, - iaload = 0x2e, - iand = 0x7e, - iastore = 0x4f, - iconst_m1 = 0x2, - iconst_0 = 0x3, - iconst_1 = 0x4, - iconst_2 = 0x5, - iconst_3 = 0x6, - iconst_4 = 0x7, - iconst_5 = 0x8, - idiv = 0x6c, - if_acmpeq = 0xa5, - if_acmpne = 0xa6, - if_icmpeq = 0x9f, - if_icmpne = 0xa0, - if_icmplt = 0xa1, - if_icmpge = 0xa2, - if_icmpgt = 0xa3, - if_icmple = 0xa4, - ifeq = 0x99, - ifne = 0x9a, - iflt = 0x9b, - ifge = 0x9c, - ifgt = 0x9d, - ifle = 0x9e, - ifnonnull = 0xc7, - ifnull = 0xc6, - iinc = 0x84, - iload = 0x15, - iload_0 = 0x1a, - iload_1 = 0x1b, - iload_2 = 0x1c, - iload_3 = 0x1d, - imul = 0x68, - ineg = 0x74, - instanceof = 0xc1, - invokedynamic = 0xba, - invokeinterface = 0xb9, - invokespecial = 0xb7, - invokestatic = 0xb8, - invokevirtual = 0xb6, - ior = 0x80, - irem = 0x70, - ireturn = 0xac, - ishl = 0x78, - ishr = 0x7a, - istore = 0x36, - istore_0 = 0x3b, - istore_1 = 0x3c, - istore_2 = 0x3d, - istore_3 = 0x3e, - isub = 0x64, - iushr = 0x7c, - ixor = 0x82, - jsr = 0xa8, - jsr_w = 0xc9, - l2d = 0x8a, - l2f = 0x89, - l2i = 0x88, - ladd = 0x61, - laload = 0x2f, - land = 0x7f, - lastore = 0x50, - lcmp = 0x94, - lconst_0 = 0x9, - lconst_1 = 0xa, - ldc = 0x12, - ldc_w = 0x13, - ldc2_w = 0x14, - ldiv = 0x6d, - lload = 0x16, - lload_0 = 0x1e, - lload_1 = 0x1f, - lload_2 = 0x20, - lload_3 = 0x21, - lmul = 0x69, - lneg = 0x75, - lookupswitch = 0xab, - lor = 0x81, - lrem = 0x71, - lreturn = 0xad, - lshl = 0x79, - lshr = 0x7b, - lstore = 0x37, - lstore_0 = 0x3f, - lstore_1 = 0x40, - lstore_2 = 0x41, - lstore_3 = 0x42, - lsub = 0x65, - lushr = 0x7d, - lxor = 0x83, - monitorenter = 0xc2, - monitorexit = 0xc3, - multianewarray = 0xc5, - new = 0xbb, - newarray = 0xbc, - nop = 0x0, - pop = 0x57, - pop2 = 0x58, - putfield = 0xb5, - putstatic = 0xb3, - ret = 0xa9, - @"return" = 0xb1, - saload = 0x35, - sastore = 0x56, - sipush = 0x11, - swap = 0x5f, - tableswitch = 0xaa, - wide = 0xc4, -}; - -fn Index(comptime T: type) type { - const bits = @typeInfo(T).int.bits; - if (bits % 8 != 0) { - @compileError("Bits should be multiple of 8"); - } - const bytes = bits / 8; - - return struct { - index: T, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - defer byte_index.* += bytes; - - const index = try if (bytes == 1) input.takeByte() else input.takeInt(T, .big); - - return .{ - .index = index, - }; - } - }; -} - -const Byte = struct { - byte: u8, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - defer byte_index.* += 1; - - return .{ - .byte = try input.takeByte(), - }; - } -}; - -fn Branch(comptime T: type) type { - const bits = @typeInfo(T).int.bits; - if (bits % 8 != 0) { - @compileError("Bits should be multiple of 8"); - } - const bytes = bits / 8; - - return struct { - branch_offset: T, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - defer byte_index.* += bytes; - - return .{ - .branch_offset = try input.takeInt(u16, .big), - }; - } - }; -} - -const IInc = struct { - index: u8, - @"const": u8, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - defer byte_index.* += 2; - - return .{ - .index = try input.takeByte(), - .@"const" = try input.takeByte(), - }; - } -}; - -const InvokeDynamic = struct { - index: u16, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - const index = try input.takeInt(u16, .big); - try input.discardAll(2); - - defer byte_index.* += 4; - - return .{ - .index = index, - }; - } -}; - -const InvokeInterface = struct { - index: u16, - count: u8, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - const index = try input.takeInt(u16, .big); - const count = try input.takeByte(); - try input.discardAll(1); - - defer byte_index.* += 4; - - return .{ - .index = index, - .count = count, - }; - } -}; - -const LookupSwitch = struct { - default: i32, - pairs: []Pair, - - const Pair = struct { - match: i32, - offset: i32, - }; - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator, byte_index: *usize) ParseError!Self { - const padded_byte_index = std.mem.alignForward(usize, byte_index.*, 4); - const offset = padded_byte_index - byte_index.*; - try input.discardAll(offset); - const default = try input.takeInt(i32, .big); - const pairs_length: usize = @intCast(try input.takeInt(i32, .big)); - const pairs = try allocator.alloc(Pair, pairs_length); - errdefer allocator.free(pairs); - - for (pairs) |*pair| { - pair.* = .{ - .match = try input.takeInt(i32, .big), - .offset = try input.takeInt(i32, .big), - }; - } - - defer byte_index.* += offset + 4 + 4 + ((4 + 4) * pairs_length); - - return .{ - .default = default, - .pairs = pairs, - }; - } - - pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - allocator.free(self.pairs); - } -}; - -const MultiANewArray = struct { - index: u16, - dimensions: u8, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - defer byte_index.* += 3; - - return .{ - .index = try input.takeInt(u16, .big), - .dimensions = try input.takeByte(), - }; - } -}; - -const NewArray = struct { - array_type: ArrayType, - - const ArrayType = enum(u8) { - boolean = 4, - char = 5, - float = 6, - double = 7, - byte = 8, - short = 9, - int = 10, - long = 11, - }; - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - const b = try input.takeByte(); - const array_type = std.enums.fromInt(ArrayType, b) orelse return ParseError.InvalidArrayType; - - defer byte_index.* += 1; - - return .{ - .array_type = array_type, - }; - } -}; - -const Short = struct { - short: u16, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - defer byte_index.* += 2; - - return .{ - .short = try input.takeInt(u16, .big), - }; - } -}; - -const TableSwitch = struct { - default: i32, - low: i32, - high: i32, - offsets: []i32, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator, byte_index: *usize) ParseError!Self { - const padded_byte_index = std.mem.alignForward(usize, byte_index.*, 4); - const offset = padded_byte_index - byte_index.*; - try input.discardAll(offset); - const default = try input.takeInt(i32, .big); - const low = try input.takeInt(i32, .big); - const high = try input.takeInt(i32, .big); - const offsets_length: usize = @intCast(high - low + 1); - const offsets = try allocator.alloc(i32, offsets_length); - errdefer allocator.free(offsets); - - for (offsets) |*o| { - o.* = try input.takeInt(i32, .big); - } - - defer byte_index.* += offset + 4 + 4 + 4 + (4 * offsets_length); - - return .{ - .default = default, - .low = low, - .high = high, - .offsets = offsets, - }; - } - - pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - allocator.free(self.offsets); - } -}; - -const Wide = union(enum) { - form1: struct { - opcode: ModifiableOp, - index: u16, - }, - form2: struct { - opcode: ModifiableOp, // Should always be iinc - index: u16, - @"const": u16, - }, - - const ModifiableOp = enum(u8) { - iload = 0x15, - fload = 0x17, - aload = 0x19, - lload = 0x16, - dload = 0x18, - istore = 0x36, - fstore = 0x38, - astore = 0x3a, - lstore = 0x37, - dstore = 0x39, - ret = 0xa9, - iinc = 0x84, - }; - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, byte_index: *usize) ParseError!Self { - const op_byte = try input.takeByte(); - const op = std.enums.fromInt(ModifiableOp, op_byte) orelse return ParseError.InvalidOp; - if (op == .iinc) { - defer byte_index.* += 5; - - return .{ - .form2 = .{ - .opcode = op, - .index = try input.takeInt(u16, .big), - .@"const" = try input.takeInt(u16, .big), - }, - }; - } else { - defer byte_index.* += 3; - - return .{ - .form1 = .{ - .opcode = op, - .index = try input.takeInt(u16, .big), - }, - }; - } - } -}; - -pub const Instruction = union(Op) { - aaload, - aastore, - aconst_null, - aload: Index(u8), - aload_0, - aload_1, - aload_2, - aload_3, - anewarray: Index(u16), - areturn, - arraylength, - astore: Index(u8), - astore_0, - astore_1, - astore_2, - astore_3, - athrow, - baload, - bastore, - bipush: Byte, - caload, - castore, - checkcast: Index(u16), - d2f, - d2i, - d2l, - dadd, - daload, - dastore, - dcmpg, - dcmpl, - dconst_0, - dconst_1, - ddiv, - dload: Index(u8), - dload_0, - dload_1, - dload_2, - dload_3, - dmul, - dneg, - drem, - dreturn, - dstore: Index(u8), - dstore_0, - dstore_1, - dstore_2, - dstore_3, - dsub, - dup, - dup_x1, - dup_x2, - dup2, - dup2_x1, - dup2_x2, - f2d, - f2i, - f2l, - fadd, - faload, - fastore, - fcmpg, - fcmpl, - fconst_0, - fconst_1, - fconst_2, - fdiv, - fload: Index(u8), - fload_0, - fload_1, - fload_2, - fload_3, - fmul, - fneg, - frem, - freturn, - fstore: Index(u8), - fstore_0, - fstore_1, - fstore_2, - fstore_3, - fsub, - getfield: Index(u16), - getstatic: Index(u16), - goto: Branch(u16), - goto_w: Branch(u32), - i2b, - i2c, - i2d, - i2f, - i2l, - i2s, - iadd, - iaload, - iand, - iastore, - iconst_m1, - iconst_0, - iconst_1, - iconst_2, - iconst_3, - iconst_4, - iconst_5, - idiv, - if_acmpeq: Branch(u16), - if_acmpne: Branch(u16), - if_icmpeq: Branch(u16), - if_icmpne: Branch(u16), - if_icmplt: Branch(u16), - if_icmpge: Branch(u16), - if_icmpgt: Branch(u16), - if_icmple: Branch(u16), - ifeq: Branch(u16), - ifne: Branch(u16), - iflt: Branch(u16), - ifge: Branch(u16), - ifgt: Branch(u16), - ifle: Branch(u16), - ifnonnull: Branch(u16), - ifnull: Branch(u16), - iinc: IInc, - iload: Index(u8), - iload_0, - iload_1, - iload_2, - iload_3, - imul, - ineg, - instanceof: Index(u16), - invokedynamic: InvokeDynamic, - invokeinterface: InvokeInterface, - invokespecial: Index(u16), - invokestatic: Index(u16), - invokevirtual: Index(u16), - ior, - irem, - ireturn, - ishl, - ishr, - istore: Index(u8), - istore_0, - istore_1, - istore_2, - istore_3, - isub, - iushr, - ixor, - jsr: Branch(u16), - jsr_w: Branch(u32), - l2d, - l2f, - l2i, - ladd, - laload, - land, - lastore, - lcmp, - lconst_0, - lconst_1, - ldc: Index(u8), - ldc_w: Index(u16), - ldc2_w: Index(u16), - ldiv, - lload: Index(u8), - lload_0, - lload_1, - lload_2, - lload_3, - lmul, - lneg, - lookupswitch: LookupSwitch, - lor, - lrem, - lreturn, - lshl, - lshr, - lstore: Index(u8), - lstore_0, - lstore_1, - lstore_2, - lstore_3, - lsub, - lushr, - lxor, - monitorenter, - monitorexit, - multianewarray: MultiANewArray, - new: Index(u16), - newarray: NewArray, - nop, - pop, - pop2, - putfield: Index(u16), - putstatic: Index(u16), - ret: Index(u8), - @"return", - saload, - sastore, - sipush: Short, - swap, - tableswitch: TableSwitch, - wide: Wide, - - const Self = @This(); - - pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator, byte_index: *usize) ParseError!Self { - const op_byte = try input.takeByte(); - const op = std.enums.fromInt(Op, op_byte) orelse return ParseError.InvalidOp; - - byte_index.* += 1; - - return switch (op) { - .aaload => .aaload, - .aastore => .aastore, - .aconst_null => .aconst_null, - .aload => .{ - .aload = try .parse(input, byte_index), - }, - .aload_0 => .aload_0, - .aload_1 => .aload_1, - .aload_2 => .aload_2, - .aload_3 => .aload_3, - .anewarray => .{ - .anewarray = try .parse(input, byte_index), - }, - .areturn => .areturn, - .arraylength => .arraylength, - .astore => .{ - .astore = try .parse(input, byte_index), - }, - .astore_0 => .astore_0, - .astore_1 => .astore_1, - .astore_2 => .astore_2, - .astore_3 => .astore_3, - .athrow => .athrow, - .baload => .baload, - .bastore => .bastore, - .bipush => .{ - .bipush = try .parse(input, byte_index), - }, - .caload => .caload, - .castore => .castore, - .checkcast => .{ - .checkcast = try .parse(input, byte_index), - }, - .d2f => .d2f, - .d2i => .d2i, - .d2l => .d2l, - .dadd => .dadd, - .daload => .daload, - .dastore => .dastore, - .dcmpg => .dcmpg, - .dcmpl => .dcmpl, - .dconst_0 => .dconst_0, - .dconst_1 => .dconst_1, - .ddiv => .ddiv, - .dload => .{ - .dload = try .parse(input, byte_index), - }, - .dload_0 => .dload_0, - .dload_1 => .dload_1, - .dload_2 => .dload_2, - .dload_3 => .dload_3, - .dmul => .dmul, - .dneg => .dneg, - .drem => .drem, - .dreturn => .dreturn, - .dstore => .{ - .dstore = try .parse(input, byte_index), - }, - .dstore_0 => .dstore_0, - .dstore_1 => .dstore_1, - .dstore_2 => .dstore_2, - .dstore_3 => .dstore_3, - .dsub => .dsub, - .dup => .dup, - .dup_x1 => .dup_x1, - .dup_x2 => .dup_x2, - .dup2 => .dup2, - .dup2_x1 => .dup2_x1, - .dup2_x2 => .dup2_x2, - .f2d => .f2d, - .f2i => .f2i, - .f2l => .f2l, - .fadd => .fadd, - .faload => .faload, - .fastore => .fastore, - .fcmpg => .fcmpg, - .fcmpl => .fcmpl, - .fconst_0 => .fconst_0, - .fconst_1 => .fconst_1, - .fconst_2 => .fconst_2, - .fdiv => .fdiv, - .fload => .{ - .fload = try .parse(input, byte_index), - }, - .fload_0 => .fload_0, - .fload_1 => .fload_1, - .fload_2 => .fload_2, - .fload_3 => .fload_3, - .fmul => .fmul, - .fneg => .fneg, - .frem => .frem, - .freturn => .freturn, - .fstore => .{ - .fstore = try .parse(input, byte_index), - }, - .fstore_0 => .fstore_0, - .fstore_1 => .fstore_1, - .fstore_2 => .fstore_2, - .fstore_3 => .fstore_3, - .fsub => .fsub, - .getfield => .{ - .getfield = try .parse(input, byte_index), - }, - .getstatic => .{ - .getstatic = try .parse(input, byte_index), - }, - .goto => .{ - .goto = try .parse(input, byte_index), - }, - .goto_w => .{ - .goto_w = try .parse(input, byte_index), - }, - .i2b => .i2b, - .i2c => .i2c, - .i2d => .i2d, - .i2f => .i2f, - .i2l => .i2l, - .i2s => .i2s, - .iadd => .iadd, - .iaload => .iaload, - .iand => .iand, - .iastore => .iastore, - .iconst_m1 => .iconst_m1, - .iconst_0 => .iconst_0, - .iconst_1 => .iconst_1, - .iconst_2 => .iconst_2, - .iconst_3 => .iconst_3, - .iconst_4 => .iconst_4, - .iconst_5 => .iconst_5, - .idiv => .idiv, - .if_acmpeq => .{ - .if_acmpeq = try .parse(input, byte_index), - }, - .if_acmpne => .{ - .if_acmpne = try .parse(input, byte_index), - }, - .if_icmpeq => .{ - .if_icmpeq = try .parse(input, byte_index), - }, - .if_icmpne => .{ - .if_icmpne = try .parse(input, byte_index), - }, - .if_icmplt => .{ - .if_icmplt = try .parse(input, byte_index), - }, - .if_icmpge => .{ - .if_icmpge = try .parse(input, byte_index), - }, - .if_icmpgt => .{ - .if_icmpgt = try .parse(input, byte_index), - }, - .if_icmple => .{ - .if_icmple = try .parse(input, byte_index), - }, - .ifeq => .{ - .ifeq = try .parse(input, byte_index), - }, - .ifne => .{ - .ifne = try .parse(input, byte_index), - }, - .iflt => .{ - .iflt = try .parse(input, byte_index), - }, - .ifge => .{ - .ifge = try .parse(input, byte_index), - }, - .ifgt => .{ - .ifgt = try .parse(input, byte_index), - }, - .ifle => .{ - .ifle = try .parse(input, byte_index), - }, - .ifnonnull => .{ - .ifnonnull = try .parse(input, byte_index), - }, - .ifnull => .{ - .ifnull = try .parse(input, byte_index), - }, - .iinc => .{ - .iinc = try .parse(input, byte_index), - }, - .iload => .{ - .iload = try .parse(input, byte_index), - }, - .iload_0 => .iload_0, - .iload_1 => .iload_1, - .iload_2 => .iload_2, - .iload_3 => .iload_3, - .imul => .imul, - .ineg => .ineg, - .instanceof => .{ - .instanceof = try .parse(input, byte_index), - }, - .invokedynamic => .{ - .invokedynamic = try .parse(input, byte_index), - }, - .invokeinterface => .{ - .invokeinterface = try .parse(input, byte_index), - }, - .invokespecial => .{ - .invokespecial = try .parse(input, byte_index), - }, - .invokestatic => .{ - .invokestatic = try .parse(input, byte_index), - }, - .invokevirtual => .{ - .invokevirtual = try .parse(input, byte_index), - }, - .ior => .ior, - .irem => .irem, - .ireturn => .ireturn, - .ishl => .ishl, - .ishr => .ishr, - .istore => .{ - .istore = try .parse(input, byte_index), - }, - .istore_0 => .istore_0, - .istore_1 => .istore_1, - .istore_2 => .istore_2, - .istore_3 => .istore_3, - .isub => .isub, - .iushr => .iushr, - .ixor => .ixor, - .jsr => .{ - .jsr = try .parse(input, byte_index), - }, - .jsr_w => .{ - .jsr_w = try .parse(input, byte_index), - }, - .l2d => .l2d, - .l2f => .l2f, - .l2i => .l2i, - .ladd => .ladd, - .laload => .laload, - .land => .land, - .lastore => .lastore, - .lcmp => .lcmp, - .lconst_0 => .lconst_0, - .lconst_1 => .lconst_1, - .ldc => .{ - .ldc = try .parse(input, byte_index), - }, - .ldc_w => .{ - .ldc_w = try .parse(input, byte_index), - }, - .ldc2_w => .{ - .ldc2_w = try .parse(input, byte_index), - }, - .ldiv => .ldiv, - .lload => .{ - .lload = try .parse(input, byte_index), - }, - .lload_0 => .lload_0, - .lload_1 => .lload_1, - .lload_2 => .lload_2, - .lload_3 => .lload_3, - .lmul => .lmul, - .lneg => .lneg, - .lookupswitch => .{ - .lookupswitch = try .parse(input, allocator, byte_index), - }, - .lor => .lor, - .lrem => .lrem, - .lreturn => .lreturn, - .lshl => .lshl, - .lshr => .lshr, - .lstore => .{ - .lstore = try .parse(input, byte_index), - }, - .lstore_0 => .lstore_0, - .lstore_1 => .lstore_1, - .lstore_2 => .lstore_2, - .lstore_3 => .lstore_3, - .lsub => .lsub, - .lushr => .lushr, - .lxor => .lxor, - .monitorenter => .monitorenter, - .monitorexit => .monitorexit, - .multianewarray => .{ - .multianewarray = try .parse(input, byte_index), - }, - .new => .{ - .new = try .parse(input, byte_index), - }, - .newarray => .{ - .newarray = try .parse(input, byte_index), - }, - .nop => .nop, - .pop => .pop, - .pop2 => .pop2, - .putfield => .{ - .putfield = try .parse(input, byte_index), - }, - .putstatic => .{ - .putstatic = try .parse(input, byte_index), - }, - .ret => .{ - .ret = try .parse(input, byte_index), - }, - .@"return" => .@"return", - .saload => .saload, - .sastore => .sastore, - .sipush => .{ - .sipush = try .parse(input, byte_index), - }, - .swap => .swap, - .tableswitch => .{ - .tableswitch = try .parse(input, allocator, byte_index), - }, - .wide => .{ - .wide = try .parse(input, byte_index), - }, - }; - } - - pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - switch (self.*) { - .lookupswitch => |*lookupswitch| lookupswitch.deinit(allocator), - .tableswitch => |*tableswitch| tableswitch.deinit(allocator), - else => {}, - } - } - - pub fn indentedFormat( - self: *const Self, - w: *std.Io.Writer, - depth: usize, - indent: u8, - constant_pool: ConstantPool, - ) std.Io.Writer.Error!void { - try w.splatByteAll(' ', depth * indent); - try w.print("type: {t}\n", .{self.*}); - - switch (self.*) { - .aload, .astore, .dload, .dstore, .fload, .fstore, .iload, .istore, .lload, .lstore => |load_store| { - try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{load_store.index}); - }, - .anewarray, .checkcast, .instanceof => |constant| { - const @"type" = constant_pool.get(constant.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("type:\n"); - try @"type".indentedFormat(w, depth, indent + 1, constant_pool); - }, - .bipush => |bipush| { - try w.splatByteAll(' ', depth * indent); - try w.print("byte: 0x{X}\n", .{bipush.byte}); - }, - .getfield, .getstatic, .putfield, .putstatic => |get_set_field| { - const field = constant_pool.get(get_set_field.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("field:\n"); - try field.indentedFormat(w, depth, indent + 1, constant_pool); - }, - .goto, .if_acmpeq, .if_acmpne, .if_icmpeq, .if_icmpne, .if_icmplt, .if_icmpge, .if_icmpgt, .if_icmple, .ifeq, .ifne, .iflt, .ifge, .ifgt, .ifle, .ifnonnull, .ifnull, .jsr => |branch| { - try w.splatByteAll(' ', depth * indent); - try w.print("branch_offset: {d}\n", .{branch.branch_offset}); - }, - .goto_w, .jsr_w => |branch_w| { - try w.splatByteAll(' ', depth * indent); - try w.print("branch_offset: {d}\n", .{branch_w.branch_offset}); - }, - .iinc => |iinc| { - try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{iinc.index}); - - try w.splatByteAll(' ', depth * indent); - try w.print("const: {d}\n", .{iinc.@"const"}); - }, - .invokedynamic => |invokedynamic| { - const call_site_specifier = constant_pool.get(invokedynamic.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("call_site_specifier:\n"); - try call_site_specifier.indentedFormat(w, depth, indent + 1, constant_pool); - }, - .invokeinterface => |invokeinterface| { - const interface_method = constant_pool.get(invokeinterface.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("interface_method:\n"); - try interface_method.indentedFormat(w, depth, indent + 1, constant_pool); - - try w.splatByteAll(' ', depth * indent); - try w.print("count: {d}\n", .{invokeinterface.count}); - }, - .invokespecial, .invokestatic, .invokevirtual => |invokespecial| { - const method = constant_pool.get(invokespecial.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("method:\n"); - try method.indentedFormat(w, depth, indent + 1, constant_pool); - }, - .ldc => |ldc| { - const value = constant_pool.get(ldc.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("value:\n"); - try value.indentedFormat(w, depth, indent + 1, constant_pool); - }, - .ldc_w, .ldc2_w => |ldc_w| { - const value = constant_pool.get(ldc_w.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("value:\n"); - try value.indentedFormat(w, depth, indent + 1, constant_pool); - }, - .lookupswitch => |lookupswitch| { - try w.splatByteAll(' ', depth * indent); - try w.print("default: {d}\n", .{lookupswitch.default}); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("pairs:\n"); - var pairs_indent = indent; - for (lookupswitch.pairs, 0..) |pair, i| { - pairs_indent += 1; - defer pairs_indent -= 1; - - try w.splatByteAll(' ', depth * pairs_indent); - try w.print("{d}:\n", .{i}); - { - pairs_indent += 1; - defer pairs_indent -= 1; - - try w.splatByteAll(' ', depth * pairs_indent); - try w.print("match: {d}\n", .{pair.match}); - - try w.splatByteAll(' ', depth * pairs_indent); - try w.print("offset: {d}\n", .{pair.offset}); - } - } - }, - .multianewarray => |multianewarray| { - const @"type" = constant_pool.get(multianewarray.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("type:\n"); - try @"type".indentedFormat(w, depth, indent + 1, constant_pool); - - try w.splatByteAll(' ', depth * indent); - try w.print("dimensions: {d}\n", .{multianewarray.dimensions}); - }, - .new => |new| { - const @"type" = constant_pool.get(new.index) catch return error.WriteFailed; - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("type:\n"); - try @"type".indentedFormat(w, depth, indent + 1, constant_pool); - }, - .newarray => |newarray| { - try w.splatByteAll(' ', depth * indent); - try w.print("type: {t}\n", .{newarray.array_type}); - }, - .ret => |ret| { - try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{ret.index}); - }, - .sipush => |sipush| { - try w.splatByteAll(' ', depth * indent); - try w.print("short: 0x{X}\n", .{sipush.short}); - }, - .tableswitch => |tableswitch| { - try w.splatByteAll(' ', depth * indent); - try w.print("default: {d}\n", .{tableswitch.default}); - - try w.splatByteAll(' ', depth * indent); - _ = try w.write("offsets:\n"); - var offsets_indent = indent; - for (tableswitch.offsets, 0..) |offset, i| { - offsets_indent += 1; - defer offsets_indent -= 1; - - try w.splatByteAll(' ', depth * offsets_indent); - try w.print("{d}: {d}\n", .{ i, offset }); - } - }, - .wide => |wide| switch (wide) { - .form1 => |form1| { - try w.splatByteAll(' ', depth * indent); - try w.print("opcode: {t}\n", .{form1.opcode}); - - try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{form1.index}); - }, - .form2 => |form2| { - try w.splatByteAll(' ', depth * indent); - try w.print("opcode: {t}\n", .{form2.opcode}); - - try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{form2.index}); - - try w.splatByteAll(' ', depth * indent); - try w.print("const: {d}\n", .{form2.@"const"}); - }, - }, - else => {}, - } - } -}; diff --git a/src/Class/ConstantPool.zig b/src/Class/ConstantPool.zig index 49668dc..54c233f 100644 --- a/src/Class/ConstantPool.zig +++ b/src/Class/ConstantPool.zig @@ -355,23 +355,23 @@ pub const Info = union(Info.Tag) { pub fn format(self: *const Info, w: *std.Io.Writer) std.Io.Writer.Error!void { switch (self.*) { - .class => |class| try w.print("#{d}", .{class.name_index}), + .class => |class| try w.print("#{d}", .{ class.name_index }), .field_ref => |field_ref| try w.print("#{d}.#{d}", .{ field_ref.class_index, field_ref.name_and_type_index }), .method_ref => |method_ref| try w.print("#{d}.#{d}", .{ method_ref.class_index, method_ref.name_and_type_index }), .interface_method_ref => |interface_method_ref| try w.print("#{d}.#{d}", .{ interface_method_ref.class_index, interface_method_ref.name_and_type_index }), - .string => |string| try w.print("#{d}", .{string.string_index}), - .integer => |integer| try w.print("{d}", .{integer.bytes}), - .float => |float| try w.print("{d}", .{float.float()}), - .long => |long| try w.print("{d}", .{long.long()}), - .double => |double| try w.print("{d}", .{double.double()}), + .string => |string| try w.print("#{d}", .{ string.string_index }), + .integer => |integer| try w.print("{d}", .{ integer.bytes }), + .float => |float| try w.print("{d}", .{ float.float() }), + .long => |long| try w.print("{d}", .{ long.long() }), + .double => |double| try w.print("{d}", .{ double.double() }), .name_and_type => |name_and_type| try w.print("#{d}:#{d}", .{ name_and_type.name_index, name_and_type.descriptor_index }), - .utf8 => |utf8| try w.print("\"{s}\"", .{utf8.bytes}), + .utf8 => |utf8| try w.print("\"{s}\"", .{ utf8.bytes }), .method_handle => |method_handle| try w.print("{t} #{d}", .{ method_handle.reference_kind, method_handle.reference_index }), - .method_type => |method_type| try w.print("#{d}", .{method_type.descriptor_index}), + .method_type => |method_type| try w.print("#{d}", .{ method_type.descriptor_index }), .dynamic => |dynamic| try w.print("#{d} #{d}", .{ dynamic.bootstrap_method_attr_index, dynamic.name_and_type_index }), .invoke_dynamic => |invoke_dynamic| try w.print("#{d} #{d}", .{ invoke_dynamic.bootstrap_method_attr_index, invoke_dynamic.name_and_type_index }), - .module => |module| try w.print("#{d}", .{module.name_index}), - .package => |package| try w.print("#{d}", .{package.name_index}), + .module => |module| try w.print("#{d}", .{ module.name_index }), + .package => |package| try w.print("#{d}", .{ package.name_index }), } } @@ -383,7 +383,7 @@ pub const Info = union(Info.Tag) { constant_pool: Self, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("constant_value_type: {t}\n", .{self.*}); + try w.print("constant_value_type: {t}\n", .{ self.* }); switch (self.*) { .class => |*class| { @@ -409,19 +409,19 @@ pub const Info = union(Info.Tag) { }, .integer => |*integer| { try w.splatByteAll(' ', depth * indent); - try w.print("integer: {d}\n", .{integer.bytes}); + try w.print("integer: {d}\n", .{ integer.bytes }); }, .float => |*float| { try w.splatByteAll(' ', depth * indent); - try w.print("float: {d}\n", .{float.float()}); + try w.print("float: {d}\n", .{ float.float() }); }, .long => |*long| { try w.splatByteAll(' ', depth * indent); - try w.print("long: {d}\n", .{long.long()}); + try w.print("long: {d}\n", .{ long.long() }); }, .double => |*double| { try w.splatByteAll(' ', depth * indent); - try w.print("double: {d}\n", .{double.double()}); + try w.print("double: {d}\n", .{ double.double() }); }, .name_and_type => |*name_and_type| { try formatInfo(w, depth, indent, "name", name_and_type, .name, constant_pool); @@ -430,11 +430,11 @@ pub const Info = union(Info.Tag) { }, .utf8 => |*utf8| { try w.splatByteAll(' ', depth * indent); - try w.print("bytes: \"{s}\"\n", .{utf8.bytes}); + try w.print("bytes: \"{s}\"\n", .{ utf8.bytes }); }, .method_handle => |*method_handle| { try w.splatByteAll(' ', depth * indent); - try w.print("kind: {t}\n", .{method_handle.reference_kind}); + try w.print("kind: {t}\n", .{ method_handle.reference_kind }); try formatInfo(w, depth, indent, "descriptor", method_handle, .reference, constant_pool); }, @@ -466,18 +466,8 @@ pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Sel const constant_pool = try allocator.alloc(?Info, constant_pool_size - 1); errdefer allocator.free(constant_pool); - var parsed: usize = 0; - errdefer { - for (0..parsed) |i| { - if (constant_pool[i]) |*info| { - info.deinit(allocator); - } - } - } - var i: usize = 0; while (i < constant_pool_size - 1) { - defer parsed = i; defer i += 1; const info: Info = try .parse(input, allocator); diff --git a/src/Class/FieldInfo.zig b/src/Class/FieldInfo.zig index a26069c..fb16e55 100644 --- a/src/Class/FieldInfo.zig +++ b/src/Class/FieldInfo.zig @@ -54,7 +54,7 @@ pub fn indentedFormat( constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.access_flags}); + try w.print("flags: {f}\n", .{ self.access_flags }); try w.splatByteAll(' ', depth * indent); _ = try w.write("name:\n"); @@ -74,7 +74,7 @@ pub fn indentedFormat( defer attr_indent -= 1; try w.splatByteAll(' ', depth * attr_indent); - try w.print("{d}:\n", .{j}); + try w.print("{d}:\n", .{ j }); try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool); } @@ -87,3 +87,4 @@ pub fn name(self: *const Self, constant_pool: ConstantPool) ResolveError!Constan pub fn descriptor(self: *const Self, constant_pool: ConstantPool) ResolveError!ConstantPool.Info { return constant_pool.getTag(self.descriptor_index, .utf8); } + diff --git a/src/Class/MethodInfo.zig b/src/Class/MethodInfo.zig index aeecd08..7d97300 100644 --- a/src/Class/MethodInfo.zig +++ b/src/Class/MethodInfo.zig @@ -57,7 +57,7 @@ pub fn indentedFormat( constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("flags: {f}\n", .{self.access_flags}); + try w.print("flags: {f}\n", .{ self.access_flags }); try w.splatByteAll(' ', depth * indent); _ = try w.write("name:\n"); @@ -77,7 +77,7 @@ pub fn indentedFormat( defer attr_indent -= 1; try w.splatByteAll(' ', depth * attr_indent); - try w.print("{d}:\n", .{j}); + try w.print("{d}:\n", .{ j }); try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool); } diff --git a/src/EnumFlags.zig b/src/EnumFlags.zig index 9b352e6..d7ca723 100644 --- a/src/EnumFlags.zig +++ b/src/EnumFlags.zig @@ -8,7 +8,13 @@ pub fn EnumFlags(comptime E: type) type { mask: BackingInt, - pub const empty: Self = .{ .data = 0 }; + pub const empty: Self = .{ .mask = 0 }; + + test empty { + const flags: EnumFlags(Enum) = .empty; + + try std.testing.expectEqual(0b0000_0000, flags.mask); + } pub fn from(mask: BackingInt) Self { return .{ @@ -16,34 +22,102 @@ pub fn EnumFlags(comptime E: type) type { }; } + test from { + const flags: EnumFlags(Enum) = .from(0b0000_0001); + + try std.testing.expectEqual(0b0000_0001, flags.mask); + } + pub fn contains(self: Self, flag: E) bool { - return (self.mask & @backingInt(flag)) != 0; + return (self.mask & @intFromEnum(flag)) != 0; } pub fn insert(self: *Self, flag: E) void { - self.mask |= @backingInt(flag); + self.mask |= @intFromEnum(flag); } pub fn remove(self: *Self, flag: E) void { - self.mask &= ~@backingInt(flag); + self.mask &= ~@intFromEnum(flag); } pub fn toggle(self: *Self, flag: E) void { - self.mask ^= @backingInt(flag); + self.mask ^= @intFromEnum(flag); } pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { var index: usize = 0; - inline for (@typeInfo(E).@"enum".field_names) |field| { - const key = @field(E, field); + inline for (std.meta.fields(E)) |field| { + const key = @field(E, field.name); if (self.contains(key)) { if (index > 0) { _ = try w.write(" | "); } - try w.print("{s}", .{field}); + try w.print("{s}", .{ field.name }); index += 1; } } } }; } + +const Enum = enum(u8) { + a = 0b0000_0001, + b = 0b0000_0010, + c = 0b0000_0100, +}; + +test { + + std.testing.refAllDecls(EnumFlags(Enum)); +} + +test "EnumFlags operations" { + var flags: EnumFlags(Enum) = .from(0b0000_0001); + + try std.testing.expect(flags.contains(Enum.a)); + + flags.remove(Enum.a); + try std.testing.expect(!flags.contains(Enum.a)); + + flags.remove(Enum.a); // Removing twice should not enable the flag + try std.testing.expect(!flags.contains(Enum.a)); + + flags.insert(Enum.b); + try std.testing.expectEqual(0b0000_0010, flags.mask); + try std.testing.expect(flags.contains(Enum.b)); + try std.testing.expect(!flags.contains(Enum.a)); + + flags.toggle(Enum.a); + try std.testing.expectEqual(0b0000_0011, flags.mask); + try std.testing.expect(flags.contains(Enum.a)); + try std.testing.expect(flags.contains(Enum.b)); + try std.testing.expect(!flags.contains(Enum.c)); +} + +fn testFormat(expected: []const u8, flags: EnumFlags(Enum)) !void { + var out_buf: [1024]u8 = undefined; + var out: std.Io.Writer = .fixed(&out_buf); + + try flags.format(&out); + + try std.testing.expectEqualStrings(expected, out.buffered()); +} + +test "EnumFlags format" { + var flags: EnumFlags(Enum) = .empty; + + flags.toggle(Enum.a); + flags.toggle(Enum.b); + flags.toggle(Enum.c); + try testFormat("a | b | c", flags); + + flags.toggle(Enum.b); + try testFormat("a | c", flags); + + flags.remove(Enum.c); + try testFormat("a", flags); + + flags.insert(Enum.b); + try testFormat("a | b", flags); +} + diff --git a/src/main.zig b/src/main.zig index 73d40b2..bf3f1f1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -19,17 +19,17 @@ pub fn main(init: std.process.Init) !void { std.debug.assert(args.skip()); const file_path = if (args.next()) |fp| fp else { try stderr.writeAll("No file argument provided.\n"); - std.process.exit(1); + return; }; const file = std.Io.Dir.cwd().openFile(io, file_path, .{}) catch |err| switch (err) { error.FileNotFound => { try stderr.writeAll("File not found.\n"); - std.process.exit(1); + return; }, error.IsDir => { try stderr.writeAll("Path is a directory.\n"); - std.process.exit(1); + return; }, else => return err, }; @@ -42,17 +42,17 @@ pub fn main(init: std.process.Init) !void { var class = Class.parse(reader, allocator) catch |err| switch (err) { error.InvalidMagicNumber => { try stderr.writeAll("Invalid magic number.\n"); - std.process.exit(1); + return; }, error.InvalidTag => { try stderr.writeAll("Unrecognized tag type.\n"); - std.process.exit(1); + return; }, else => return err, }; defer class.deinit(allocator); - try stdout.print("{f}", .{class}); + try stdout.print("{f}", .{ class }); try stdout.flush(); } diff --git a/testsuite/classes/java/Main.java b/testsuite/classes/java/Main.java index 9b9cfa6..0f33998 100644 --- a/testsuite/classes/java/Main.java +++ b/testsuite/classes/java/Main.java @@ -17,52 +17,6 @@ public class Main implements Runnable, Supplier, Interface { } finally { System.err.println("Finally block"); } - - var a = 8; - a <<= 3; - final var b = a >> 1; - switch (b) { - case 1: - break; - case 32: - System.out.println("Good"); - break; - default: - System.out.println("Number " + a); - break; - } - - final var o = getObject(); - switch (o) { - case Integer i: - switch (i) { - case 1: - System.out.println("One"); - break; - case 2: - System.out.println("Two"); - break; - case 3: - System.out.println("Three"); - break; - default: - break; - } - break; - default: - System.out.println("Something else"); - break; - } - - inc(5); - } - - private static Object getObject() { - return 3; - } - - private static void inc(int i) { - i += 1000; } @Override diff --git a/testsuite/classes/java/Object.class b/testsuite/classes/java/Object.class new file mode 100644 index 0000000..d33531f Binary files /dev/null and b/testsuite/classes/java/Object.class differ