Add additional predefined attribute infos

This commit is contained in:
ktkk 2026-07-04 18:10:33 +02:00
parent 75d023cfe1
commit 9af766e495
3 changed files with 317 additions and 12 deletions

View file

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

View file

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

View file

@ -66,4 +66,3 @@ pub fn main(init: std.process.Init) !void {
try stdout.flush();
}