java-class-parser/src/Class/MethodInfo.zig
2026-07-05 01:08:13 +02:00

101 lines
3.4 KiB
Zig

const std = @import("std");
const EnumFlags = @import("../EnumFlags.zig").EnumFlags;
const Class = @import("../Class.zig");
const ConstantPoolInfo = Class.ConstantPoolInfo;
const AttributeInfo = Class.AttributeInfo;
const ResolveError = Class.ResolveError;
access_flags: MethodAccessFlags,
name_index: u16,
descriptor_index: u16,
attributes: []AttributeInfo,
const Self = @This();
pub const MethodAccessFlags = EnumFlags(enum(u16) {
public = 0x0001,
private = 0x0002,
protected = 0x0004,
static = 0x0008,
final = 0x0010,
synchronized = 0x0020,
bridge = 0x0040,
varargs = 0x0080,
native = 0x0100,
abstract = 0x0400,
strict = 0x0800,
synthetic = 0x1000,
});
pub fn parse(input: *std.Io.Reader, constant_pool: []const ?ConstantPoolInfo, allocator: std.mem.Allocator) !Self {
const access_flags: MethodAccessFlags = .{ .mask = try input.takeInt(u16, .big) };
const name_index = try input.takeInt(u16, .big);
const descriptor_index = try input.takeInt(u16, .big);
const attributes = try Class.parseAttributes(input, constant_pool, allocator);
return .{
.access_flags = access_flags,
.name_index = name_index,
.descriptor_index = descriptor_index,
.attributes = attributes,
};
}
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
for (self.attributes) |*attr_info| {
attr_info.deinit(allocator);
}
allocator.free(self.attributes);
}
pub fn indentedFormat(
self: *const Self,
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("flags: {f}\n", .{ self.access_flags });
try w.splatByteAll(' ', depth * indent);
_ = try w.write("name:\n");
const method_name = self.name(constant_pool) catch return error.WriteFailed;
try method_name.indentedFormat(w, depth, indent + 1, constant_pool);
try w.splatByteAll(' ', depth * indent);
_ = try w.write("descriptor:\n");
const method_descriptor = self.descriptor(constant_pool) catch return error.WriteFailed;
try method_descriptor.indentedFormat(w, depth, indent + 1, constant_pool);
try w.splatByteAll(' ', depth * indent);
_ = try w.write("attributes:\n");
var attr_indent = indent;
for (self.attributes, 0..) |*attribute, j| {
attr_indent += 1;
defer attr_indent -= 1;
try w.splatByteAll(' ', depth * attr_indent);
try w.print("{d}:\n", .{ j });
try attribute.indentedFormat(w, depth, attr_indent + 1, constant_pool);
}
}
pub fn name(self: *const Self, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
}
pub fn descriptor(self: *const Self, constant_pool: []const ?ConstantPoolInfo) ResolveError!ConstantPoolInfo {
const descriptor_index = self.descriptor_index - 1;
if (descriptor_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[descriptor_index];
if (cp_info == null or @as(ConstantPoolInfo.Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
}