diff --git a/src/Class.zig b/src/Class.zig index ff1a581..be8324b 100644 --- a/src/Class.zig +++ b/src/Class.zig @@ -33,14 +33,14 @@ 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,8 +121,12 @@ 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 FieldInfo.parse(input, constant_pool, allocator); + fields[i] = try .parse(input, constant_pool, allocator); + parsed += 1; } return fields; @@ -133,8 +137,12 @@ 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; @@ -145,8 +153,12 @@ 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 AttributeInfo.parse(input, constant_pool, allocator); + attributes[i] = try .parse(input, constant_pool, allocator); + parsed += 1; } return attributes; @@ -154,58 +166,34 @@ 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"); @@ -224,7 +212,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); } @@ -234,7 +222,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); } @@ -244,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 method.indentedFormat(w, depth, indent + 1, self.constant_pool); } @@ -254,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 attribute.indentedFormat(w, depth, indent + 1, self.constant_pool); } } @@ -266,4 +254,3 @@ 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 e138b98..e8c2295 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,7 +319,7 @@ pub const AttributeInfo = union(enum) { defer instr_indent -= 1; try w.splatByteAll(' ', depth * instr_indent); - try w.print("{d}:\n", .{ i }); + try w.print("{d}:\n", .{i}); try instr.indentedFormat(w, depth, instr_indent + 1, constant_pool); } @@ -332,7 +332,7 @@ pub const AttributeInfo = union(enum) { defer exception_indent -= 1; try w.splatByteAll(' ', depth * exception_indent); - try w.print("{d}:\n", .{ i }); + try w.print("{d}:\n", .{i}); try exception.indentedFormat(w, depth, exception_indent + 1, constant_pool); } @@ -345,7 +345,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 +359,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 +375,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 +388,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 +420,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 +431,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 +445,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 +459,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 +474,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 +487,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 +500,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 +513,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 +526,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 +539,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 +557,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 +570,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 +586,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 +613,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 +626,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 +641,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); } }, @@ -714,13 +714,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| { @@ -746,6 +746,10 @@ pub const Code = struct { 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, @@ -753,11 +757,13 @@ pub const Code = struct { }; try instructions.append(allocator, try .parse(code, allocator, &byte_index)); + parsed_instructions += 1; } 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), @@ -770,8 +776,13 @@ 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 .{ @@ -788,7 +799,9 @@ pub const Code = struct { instruction.deinit(allocator); } allocator.free(self.code); + allocator.free(self.exception_table); + for (self.attributes) |*attr| { attr.deinit(allocator); } @@ -839,13 +852,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 => .{ @@ -864,6 +877,7 @@ 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); } @@ -881,6 +895,7 @@ 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); } @@ -888,6 +903,7 @@ 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); } @@ -923,7 +939,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| { @@ -935,14 +951,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"); @@ -952,18 +968,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"); @@ -973,14 +989,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"); @@ -990,7 +1006,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); } @@ -1003,7 +1019,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); } @@ -1081,7 +1097,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| { @@ -1092,7 +1108,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 => {}, } @@ -1103,8 +1119,13 @@ 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 .{ @@ -1129,6 +1150,7 @@ 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); } @@ -1175,7 +1197,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); @@ -1214,6 +1236,7 @@ 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), @@ -1255,7 +1278,7 @@ pub const EnclosingMethod = struct { } }; -pub const Synthetic = struct { }; +pub const Synthetic = struct {}; pub const Signature = struct { signature_index: u16, @@ -1321,10 +1344,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}); } }; @@ -1332,6 +1355,7 @@ 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), @@ -1369,10 +1393,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); @@ -1398,6 +1422,7 @@ 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), @@ -1438,10 +1463,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); @@ -1467,6 +1492,7 @@ 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), @@ -1487,7 +1513,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 @@ -1504,7 +1530,7 @@ pub const ElementValue = union(enum) { }, pub const ConstValue = struct { - @"type": Type, + type: Type, index: u16, pub const Type = enum(u8) { @@ -1521,7 +1547,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_; @@ -1572,7 +1598,7 @@ pub const ElementValue = union(enum) { return switch (tag) { 'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 's' => .{ .const_value = .{ - .@"type" = @enumFromInt(tag), + .type = @fromBackingInt(@intCast(tag)), .index = try input.takeInt(u16, .big), }, }, @@ -1595,8 +1621,13 @@ 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 .{ @@ -1629,7 +1660,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| { @@ -1668,7 +1699,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); } @@ -1717,11 +1748,16 @@ 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 .{ @@ -1744,7 +1780,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); @@ -1757,7 +1793,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); } } @@ -1776,8 +1812,13 @@ 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 .{ @@ -1802,8 +1843,13 @@ 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 .{ @@ -1822,6 +1868,33 @@ 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, @@ -1837,7 +1910,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); } } @@ -1852,17 +1925,13 @@ pub const RuntimeVisibleParameterAnnotations = struct { const num_parameters = try input.takeByte(); const parameter_annotations = try allocator.alloc(ParameterAnnotation, num_parameters); errdefer allocator.free(parameter_annotations); - for (parameter_annotations) |*parameter_annotation| { - 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, - }; + 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; } return .{ @@ -1871,11 +1940,8 @@ pub const RuntimeVisibleParameterAnnotations = struct { } pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - for (self.parameter_annotations) |parameter_annotation| { - for (parameter_annotation.annotations) |*annotation| { - annotation.deinit(allocator); - } - allocator.free(parameter_annotation.annotations); + for (self.parameter_annotations) |*parameter_annotation| { + parameter_annotation.deinit(allocator); } allocator.free(self.parameter_annotations); } @@ -1890,17 +1956,13 @@ pub const RuntimeInvisibleParameterAnnotations = struct { const num_parameters = try input.takeByte(); const parameter_annotations = try allocator.alloc(ParameterAnnotation, num_parameters); errdefer allocator.free(parameter_annotations); - for (parameter_annotations) |*parameter_annotation| { - 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, - }; + 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; } return .{ @@ -1909,11 +1971,8 @@ pub const RuntimeInvisibleParameterAnnotations = struct { } pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { - for (self.parameter_annotations) |parameter_annotation| { - for (parameter_annotation.annotations) |*annotation| { - annotation.deinit(allocator); - } - allocator.free(parameter_annotation.annotations); + for (self.parameter_annotations) |*parameter_annotation| { + parameter_annotation.deinit(allocator); } allocator.free(self.parameter_annotations); } @@ -2002,7 +2061,7 @@ pub const TypeAnnotation = struct { bound_index: u8, }; - pub const Empty = struct { }; + pub const Empty = struct {}; pub const FormalParameter = struct { formal_parameter_index: u8, @@ -2027,13 +2086,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}); } }; }; @@ -2058,31 +2117,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); @@ -2093,25 +2152,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 => {}, } @@ -2132,10 +2191,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}); } }; @@ -2143,6 +2202,7 @@ 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(), @@ -2173,14 +2233,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 = @enumFromInt(try input.takeInt(u8, .big)); + const target_type: TargetType = @fromBackingInt(@intCast(try input.takeInt(u8, .big))); const target_info: TargetInfo = switch (target_type) { .type_parameter_generic_class_interface, .type_parameter_generic_method_constructor => .{ .type_parameter = .{ @@ -2215,6 +2275,7 @@ 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), @@ -2230,7 +2291,7 @@ pub const TypeAnnotation = struct { }; }, .type_in_exception_parameter => .{ - .@"catch" = . { + .@"catch" = .{ .exception_table_index = try input.takeInt(u16, .big), }, }, @@ -2255,11 +2316,16 @@ 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 .{ @@ -2276,6 +2342,7 @@ 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); } @@ -2290,7 +2357,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"); @@ -2300,7 +2367,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); @@ -2313,7 +2380,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); } } @@ -2332,8 +2399,13 @@ 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 .{ @@ -2358,8 +2430,13 @@ 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 .{ @@ -2422,7 +2499,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); } } @@ -2436,12 +2513,17 @@ 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); } @@ -2450,6 +2532,7 @@ pub const BootstrapMethods = struct { .bootstrap_method_ref = bootstrap_method_ref, .bootstrap_arguments = bootstrap_arguments, }; + parsed += 1; } return .{ @@ -2488,7 +2571,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| { @@ -2507,6 +2590,7 @@ 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), @@ -2567,7 +2651,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| { @@ -2609,7 +2693,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"); @@ -2621,7 +2705,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); } } @@ -2654,7 +2738,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"); @@ -2666,7 +2750,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); } } @@ -2702,7 +2786,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); } } @@ -2720,58 +2804,71 @@ 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 = requires_index, - .requires_flags = requires_flags, - .requires_version_index = requires_version_index, + .requires_index = try input.takeInt(u16, .big), + .requires_flags = .from(try input.takeInt(u16, .big)), + .requires_version_index = try input.takeInt(u16, .big), }; } 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); } @@ -2779,18 +2876,25 @@ 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 .{ @@ -2807,15 +2911,19 @@ 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); } @@ -2835,7 +2943,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| { @@ -2852,7 +2960,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); } @@ -2864,7 +2972,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); } @@ -2876,7 +2984,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); } @@ -2890,7 +2998,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); } @@ -2902,7 +3010,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); } } @@ -2925,6 +3033,7 @@ 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); } @@ -2979,6 +3088,7 @@ 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); } @@ -3010,8 +3120,13 @@ 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 .{ @@ -3053,7 +3168,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); } } @@ -3070,8 +3185,13 @@ 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 .{ @@ -3095,6 +3215,7 @@ 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 index 494dc8b..5d2b6f8 100644 --- a/src/Class/Code/Instruction.zig +++ b/src/Class/Code/Instruction.zig @@ -341,6 +341,7 @@ const LookupSwitch = struct { 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), @@ -437,6 +438,7 @@ const TableSwitch = struct { 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); } @@ -748,7 +750,7 @@ pub const Instruction = union(Op) { .athrow => .athrow, .baload => .baload, .bastore => .bastore, - .bipush => .{ + .bipush => .{ .bipush = try .parse(input, byte_index), }, .caload => .caload, @@ -1054,12 +1056,12 @@ pub const Instruction = union(Op) { constant_pool: ConstantPool, ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); - try w.print("type: {t}\n", .{ self.* }); + 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 }); + try w.print("index: {d}\n", .{load_store.index}); }, .anewarray, .checkcast, .instanceof => |constant| { const @"type" = constant_pool.get(constant.index) catch return error.WriteFailed; @@ -1070,7 +1072,7 @@ pub const Instruction = union(Op) { }, .bipush => |bipush| { try w.splatByteAll(' ', depth * indent); - try w.print("byte: 0x{X}\n", .{ bipush.byte }); + 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; @@ -1081,18 +1083,18 @@ pub const Instruction = union(Op) { }, .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 }); + 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 }); + 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.print("index: {d}\n", .{iinc.index}); try w.splatByteAll(' ', depth * indent); - try w.print("const: {d}\n", .{ iinc.@"const" }); + try w.print("const: {d}\n", .{iinc.@"const"}); }, .invokedynamic => |invokedynamic| { const call_site_specifier = constant_pool.get(invokedynamic.index) catch return error.WriteFailed; @@ -1109,7 +1111,7 @@ pub const Instruction = union(Op) { try interface_method.indentedFormat(w, depth, indent + 1, constant_pool); try w.splatByteAll(' ', depth * indent); - try w.print("count: {d}\n", .{ invokeinterface.count }); + try w.print("count: {d}\n", .{invokeinterface.count}); }, .invokespecial, .invokestatic, .invokevirtual => |invokespecial| { const method = constant_pool.get(invokespecial.index) catch return error.WriteFailed; @@ -1134,7 +1136,7 @@ pub const Instruction = union(Op) { }, .lookupswitch => |lookupswitch| { try w.splatByteAll(' ', depth * indent); - try w.print("default: {d}\n", .{ lookupswitch.default }); + try w.print("default: {d}\n", .{lookupswitch.default}); try w.splatByteAll(' ', depth * indent); _ = try w.write("pairs:\n"); @@ -1144,16 +1146,16 @@ pub const Instruction = union(Op) { defer pairs_indent -= 1; try w.splatByteAll(' ', depth * pairs_indent); - try w.print("{d}:\n", .{ i }); + 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.print("match: {d}\n", .{pair.match}); try w.splatByteAll(' ', depth * pairs_indent); - try w.print("offset: {d}\n", .{ pair.offset }); + try w.print("offset: {d}\n", .{pair.offset}); } } }, @@ -1165,7 +1167,7 @@ pub const Instruction = union(Op) { try @"type".indentedFormat(w, depth, indent + 1, constant_pool); try w.splatByteAll(' ', depth * indent); - try w.print("dimensions: {d}\n", .{ multianewarray.dimensions }); + try w.print("dimensions: {d}\n", .{multianewarray.dimensions}); }, .new => |new| { const @"type" = constant_pool.get(new.index) catch return error.WriteFailed; @@ -1176,19 +1178,19 @@ pub const Instruction = union(Op) { }, .newarray => |newarray| { try w.splatByteAll(' ', depth * indent); - try w.print("type: {t}\n", .{ newarray.array_type }); + try w.print("type: {t}\n", .{newarray.array_type}); }, .ret => |ret| { try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{ ret.index }); + try w.print("index: {d}\n", .{ret.index}); }, .sipush => |sipush| { try w.splatByteAll(' ', depth * indent); - try w.print("short: 0x{X}\n", .{ sipush.short }); + 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.print("default: {d}\n", .{tableswitch.default}); try w.splatByteAll(' ', depth * indent); _ = try w.write("offsets:\n"); @@ -1204,24 +1206,23 @@ pub const Instruction = union(Op) { .wide => |wide| switch (wide) { .form1 => |form1| { try w.splatByteAll(' ', depth * indent); - try w.print("opcode: {t}\n", .{ form1.opcode }); + try w.print("opcode: {t}\n", .{form1.opcode}); try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{ form1.index }); + 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.print("opcode: {t}\n", .{form2.opcode}); try w.splatByteAll(' ', depth * indent); - try w.print("index: {d}\n", .{ form2.index }); + try w.print("index: {d}\n", .{form2.index}); try w.splatByteAll(' ', depth * indent); - try w.print("const: {d}\n", .{ form2.@"const" }); + try w.print("const: {d}\n", .{form2.@"const"}); }, }, else => {}, } } }; - diff --git a/src/Class/ConstantPool.zig b/src/Class/ConstantPool.zig index 54c233f..49668dc 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,8 +466,18 @@ 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 fb16e55..a26069c 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,4 +87,3 @@ 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 7d97300..aeecd08 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 7fcf1a3..9b352e6 100644 --- a/src/EnumFlags.zig +++ b/src/EnumFlags.zig @@ -17,19 +17,19 @@ pub fn EnumFlags(comptime E: type) type { } pub fn contains(self: Self, flag: E) bool { - return (self.mask & @intFromEnum(flag)) != 0; + return (self.mask & @backingInt(flag)) != 0; } pub fn insert(self: *Self, flag: E) void { - self.mask |= @intFromEnum(flag); + self.mask |= @backingInt(flag); } pub fn remove(self: *Self, flag: E) void { - self.mask &= ~@intFromEnum(flag); + self.mask &= ~@backingInt(flag); } pub fn toggle(self: *Self, flag: E) void { - self.mask ^= @intFromEnum(flag); + self.mask ^= @backingInt(flag); } pub fn format(self: *const Self, w: *std.Io.Writer) std.Io.Writer.Error!void { @@ -40,11 +40,10 @@ pub fn EnumFlags(comptime E: type) type { if (index > 0) { _ = try w.write(" | "); } - try w.print("{s}", .{ field }); + try w.print("{s}", .{field}); index += 1; } } } }; } - diff --git a/src/main.zig b/src/main.zig index bf3f1f1..73d40b2 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"); - return; + std.process.exit(1); }; const file = std.Io.Dir.cwd().openFile(io, file_path, .{}) catch |err| switch (err) { error.FileNotFound => { try stderr.writeAll("File not found.\n"); - return; + std.process.exit(1); }, error.IsDir => { try stderr.writeAll("Path is a directory.\n"); - return; + std.process.exit(1); }, 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"); - return; + std.process.exit(1); }, error.InvalidTag => { try stderr.writeAll("Unrecognized tag type.\n"); - return; + std.process.exit(1); }, else => return err, }; defer class.deinit(allocator); - try stdout.print("{f}", .{ class }); + try stdout.print("{f}", .{class}); try stdout.flush(); }