diff --git a/src/Class.zig b/src/Class.zig index 787f7c2..1d96a19 100644 --- a/src/Class.zig +++ b/src/Class.zig @@ -675,7 +675,13 @@ pub const ConstantPoolInfo = union(ConstantPoolInfo.Tag) { } } - pub fn indentedFormat(self: *const ConstantPoolInfo, w: *std.Io.Writer, depth: usize, indent: u8, constant_pool: []const ?ConstantPoolInfo) std.Io.Writer.Error!void { + pub fn indentedFormat( + self: *const ConstantPoolInfo, + w: *std.Io.Writer, + depth: usize, + indent: u8, + constant_pool: []const ?ConstantPoolInfo, + ) std.Io.Writer.Error!void { try w.splatByteAll(' ', depth * indent); try w.print("constant_value_type: {s}\n", .{ @tagName(self.*) }); diff --git a/src/Class/AttributeInfo.zig b/src/Class/AttributeInfo.zig index c5eb83c..4b17b67 100644 --- a/src/Class/AttributeInfo.zig +++ b/src/Class/AttributeInfo.zig @@ -28,8 +28,18 @@ pub const AttributeInfo = union(enum) { runtime_invisible_annotations: RuntimeInvisibleAnnotations, runtime_visible_parameter_annotations: RuntimeVisibleParameterAnnotations, runtime_invisible_parameter_annotations: RuntimeInvisibleParameterAnnotations, + // runtime_visible_type_annotations: RuntimeVisibleTypeAnnotations, + // runtime_invisible_type_annotations: RuntimeInvisibleTypeAnnotations, annotation_default: AnnotationDefault, bootstrap_methods: BootstrapMethods, + method_parameters: MethodParameters, + // module: Module, + module_packages: ModulePackages, + module_main_class: ModuleMainClass, + nest_host: NestHost, + nest_members: NestMembers, + record: Record, + permitted_subclasses: PermittedSubclasses, }, const Self = @This(); @@ -167,6 +177,48 @@ pub const AttributeInfo = union(enum) { .bootstrap_methods = try BootstrapMethods.parse(limited, allocator), }, }; + } else if (std.mem.eql(u8, attribute_name.bytes, "MethodParameters")) { + return .{ + .predefined = .{ + .method_parameters = try MethodParameters.parse(limited, allocator), + }, + }; + } else if (std.mem.eql(u8, attribute_name.bytes, "ModulePackages")) { + return .{ + .predefined = .{ + .module_packages = try ModulePackages.parse(limited, allocator), + }, + }; + } else if (std.mem.eql(u8, attribute_name.bytes, "ModuleMainClass")) { + return .{ + .predefined = .{ + .module_main_class = try ModuleMainClass.parse(limited), + }, + }; + } else if (std.mem.eql(u8, attribute_name.bytes, "NestHost")) { + return .{ + .predefined = .{ + .nest_host = try NestHost.parse(limited), + }, + }; + } else if (std.mem.eql(u8, attribute_name.bytes, "NestMembers")) { + return .{ + .predefined = .{ + .nest_members = try NestMembers.parse(limited, allocator), + }, + }; + } else if (std.mem.eql(u8, attribute_name.bytes, "Record")) { + return .{ + .predefined = .{ + .record = try Record.parse(limited, constant_pool, allocator), + }, + }; + } else if (std.mem.eql(u8, attribute_name.bytes, "PermittedSubclasses")) { + return .{ + .predefined = .{ + .permitted_subclasses = try PermittedSubclasses.parse(limited, allocator), + }, + }; } else { return .{ .new = try NewAttribute.parse(limited, attribute_name_index + 1, attribute_length, allocator), @@ -192,6 +244,11 @@ pub const AttributeInfo = union(enum) { .runtime_invisible_parameter_annotations => |*runtime_invisible_parameter_annotations| runtime_invisible_parameter_annotations.deinit(allocator), .annotation_default => |*annotation_default| annotation_default.deinit(allocator), .bootstrap_methods => |*bootstrap_methods| bootstrap_methods.deinit(allocator), + .method_parameters => |*method_parameters| method_parameters.deinit(allocator), + .module_packages => |*module_packages| module_packages.deinit(allocator), + .nest_members => |*nest_members| nest_members.deinit(allocator), + .record => |*record| record.deinit(allocator), + .permitted_subclasses => |*permitted_subclasses| permitted_subclasses.deinit(allocator), else => {}, }, } @@ -318,10 +375,14 @@ pub const AttributeInfo = union(enum) { .synthetic => {}, .signature => |attr| { const signature = attr.signature(constant_pool) catch return error.WriteFailed; + try w.splatByteAll(' ', depth * indent); + _ = try w.write("signature:\n"); try signature.indentedFormat(w, depth, indent + 1, constant_pool); }, .source_file => |attr| { const source_file = attr.sourceFile(constant_pool) catch return error.WriteFailed; + try w.splatByteAll(' ', depth * indent); + _ = try w.write("source_file:\n"); try source_file.indentedFormat(w, depth, indent + 1, constant_pool); }, //.source_debug_extension, @@ -335,6 +396,14 @@ pub const AttributeInfo = union(enum) { //.runtime_invisible_parameter_annotations, //.annotation_default, //.bootstrap_methods, + //.method_parameters, + //.module, + //.module_packages, + //.module_main_class, + //.nest_host, + //.nest_members, + //.record, + //.permitted_subclasses, else => {}, } }, @@ -970,18 +1039,18 @@ pub const Deprecated = struct { }; pub const ElementValue = union(enum) { // B, C, D, F, I, J, S, Z, s - const_value_index: u16, + const_value_index: u16, // e - enum_const_value: struct { + enum_const_value: struct { type_name_index: u16, const_name_index: u16, }, // c - class_info_index: u16, + class_info_index: u16, // @ - annotation_value: Annotation, + annotation_value: Annotation, // [ - array_value: struct { + array_value: struct { values: []ElementValue, }, @@ -1035,15 +1104,15 @@ pub const ElementValue = union(enum) { } }; +pub const ElementValuePair = struct { + element_name_index: u16, + value: ElementValue, +}; + pub const Annotation = struct { type_index: u16, element_value_pairs: []ElementValuePair, - pub const ElementValuePair = struct { - element_name_index: u16, - value: ElementValue, - }; - pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Annotation { const type_index = try input.takeInt(u16, .big); @@ -1203,6 +1272,51 @@ pub const RuntimeInvisibleParameterAnnotations = struct { } }; +// TODO: TypeAnnotation structure +// pub const TypeAnnotation = struct { +// target_info: union(TargetType) { +// type_parameter_target: TypeParameterTarget, +// supertype_target: SupertypeTarget, +// type_parameter_bound_target: TypeParameterBoundTarget, +// emtpy_target: EmptyTarget, +// formal_parameter_target: FormalParameterTarget, +// throws_target: ThrowsTarget, +// localvar_target: LocalvarTarget, +// catch_target: CatchTarget, +// offset_target: OffsetTarget, +// type_argument_target: TypeArgumentTarget, +// }, +// target_path: TypePath, +// type_index: u16, +// element_value_pairs: []ElementValuePair, +// +// pub const TargetType = enum(u8) { +// type_parameter_target = 0x00, +// type +// }; +// +// pub const TypePath = struct { +// path: []Path, +// +// pub const Path = struct { +// type_path_kind: u8, +// type_argument_index: u8, +// }; +// }; +// }; + +// pub const RuntimeVisibleTypeAnnotations = struct { +// type_annotations: []TypeAnnotation, +// +// const Self = @This(); +// }; +// +// pub const RuntimeInvisibleTypeAnnotations = struct { +// type_annotations: []TypeAnnotation, +// +// const Self = @This(); +// }; + pub const AnnotationDefault = struct { default_value: ElementValue, @@ -1261,3 +1375,189 @@ pub const BootstrapMethods = struct { allocator.free(self.bootstrap_methods); } }; + +pub const MethodParameters = struct { + parameters: []Parameter, + + const Self = @This(); + + pub const Parameter = struct { + name_index: u16, + access_flags: ParameterAccessFlags, + + pub const ParameterFlags = enum(u16) { + final = 0x0010, + synthetic = 0x1000, + mandated = 0x8000, + }; + + pub const ParameterAccessFlags = EnumFlags(ParameterFlags); + }; + + pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self { + 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), + .access_flags = .{ .mask = try input.takeInt(u16, .big) }, + }; + } + + return .{ + .parameters = parameters, + }; + } + + pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + allocator.free(self.parameters); + } +}; + +pub const ModulePackages = struct { + package_indeces: []u16, + + const Self = @This(); + + pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self { + 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); + } + + return .{ + .package_indeces = package_indeces, + }; + } + + pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + allocator.free(self.package_indeces); + } +}; + +pub const ModuleMainClass = struct { + main_class_index: u16, + + const Self = @This(); + + pub fn parse(input: *std.Io.Reader) ParseError!Self { + return .{ + .main_class_index = try input.takeInt(u16, .big), + }; + } +}; + +pub const NestHost = struct { + host_class_index: u16, + + const Self = @This(); + + pub fn parse(input: *std.Io.Reader) ParseError!Self { + return .{ + .host_class_index = try input.takeInt(u16, .big), + }; + } +}; + +pub const NestMembers = struct { + classes: []u16, + + const Self = @This(); + + 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); + } + + return .{ + .classes = classes, + }; + } + + pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + allocator.free(self.classes); + } +}; + +pub const Record = struct { + components: []RecordComponentInfo, + + const Self = @This(); + + pub const RecordComponentInfo = struct { + name_index: u16, + descriptor_index: u16, + attributes: []AttributeInfo, + + pub fn parse(input: *std.Io.Reader, constant_pool: []const ?ConstantPoolInfo, allocator: std.mem.Allocator) (ParseError || ResolveError)!RecordComponentInfo { + const name_index = try input.takeInt(u16, .big); + const descriptor_index = try input.takeInt(u16, .big); + + const attribute_count = try input.takeInt(u16, .big); + const attributes = try allocator.alloc(AttributeInfo, attribute_count); + errdefer allocator.free(attributes); + for (attributes) |*attribute| { + attribute.* = try .parse(input, constant_pool, allocator); + } + + return .{ + .name_index = name_index, + .descriptor_index = descriptor_index, + .attributes = attributes, + }; + } + + pub fn deinit(self: *RecordComponentInfo, allocator: std.mem.Allocator) void { + for (self.attributes) |*attribute| { + attribute.deinit(allocator); + } + allocator.free(self.attributes); + } + }; + + pub fn parse(input: *std.Io.Reader, constant_pool: []const ?ConstantPoolInfo, allocator: std.mem.Allocator) (ParseError || ResolveError)!Self { + const components_count = try input.takeInt(u16, .big); + const components = try allocator.alloc(RecordComponentInfo, components_count); + for (components) |*component| { + component.* = try .parse(input, constant_pool, allocator); + } + + return .{ + .components = components, + }; + } + + pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + for (self.components) |*component| { + component.deinit(allocator); + } + allocator.free(self.components); + } +}; + +pub const PermittedSubclasses = struct { + classes: []u16, + + const Self = @This(); + + 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); + } + + return .{ + .classes = classes, + }; + } + + pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { + allocator.free(self.classes); + } +}; diff --git a/src/main.zig b/src/main.zig index 4ea41ec..922c825 100644 --- a/src/main.zig +++ b/src/main.zig @@ -66,4 +66,3 @@ pub fn main(init: std.process.Init) !void { try stdout.flush(); } -