Fix leaky error handling + Zig fmt

This commit is contained in:
ktkk 2026-11-03 16:29:08 +00:00
parent 8e2cd4d7a2
commit 7bd22b7b80
8 changed files with 344 additions and 227 deletions

View file

@ -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,49 +166,25 @@ 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;
@ -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);
}

View file

@ -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);
}
@ -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);
}
@ -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);
}
@ -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),
@ -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),
@ -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),
@ -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),
@ -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 .{
@ -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);
@ -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,
@ -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);
}
@ -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(),
@ -2180,7 +2240,7 @@ pub const TypeAnnotation = struct {
};
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),
@ -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);
}
@ -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);
@ -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 .{
@ -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 .{
@ -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),
@ -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);
}
@ -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 .{
@ -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);
}

View file

@ -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);
}
@ -1224,4 +1226,3 @@ pub const Instruction = union(Op) {
}
}
};

View file

@ -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);

View file

@ -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);
}

View file

@ -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 {
@ -47,4 +47,3 @@ pub fn EnumFlags(comptime E: type) type {
}
};
}

View file

@ -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,11 +42,11 @@ 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,
};