rjvm/bytecode/reader/
containers.rs1use crate::bytecode::flags::{ClassAccessFlags, FieldAccessFlags, MethodAccessFlags};
2use crate::bytecode::pool::{ConstantPool, ConstantPoolIndex};
3use crate::bytecode::reader::attributes::read_attribute;
4use crate::bytecode::reader::constants::read_constant_pool_entry;
5use crate::bytecode::reader::BufferedReader;
6use crate::bytecode::{
7 BaseType, BytecodeError, ClassFile, ClassFileVersion, Descriptor, DescriptorKind, Field,
8 FieldType, Interface, Method,
9};
10
11pub fn read_classfile(
12 reader: &mut BufferedReader,
13 cp: &mut ConstantPool,
14) -> Result<ClassFile, BytecodeError> {
15 let magic_number = reader.take::<u32>()?;
16 if magic_number != 0xCAFEBABE {
17 return Err(BytecodeError::InvalidClassFile);
18 }
19
20 let minor_version = reader.take::<u16>()?;
21 let major_version = reader.take::<u16>()?;
22 let version = ClassFileVersion {
23 minor: minor_version,
24 major: major_version,
25 };
26
27 let constant_pool_count = reader.take::<u16>()?;
28 for idx in 1..=constant_pool_count - 1 {
29 let entry = read_constant_pool_entry(reader, cp)?;
30 cp.insert(idx.into(), entry)?;
31 }
32
33 let access_flags = reader.take::<u16>()?;
34 let access_flags = match ClassAccessFlags::from_bits(access_flags) {
35 Some(flags) => flags,
36 None => return Err(BytecodeError::InvalidClassFile),
37 };
38
39 let this_class = reader.take::<u16>()?;
40 let this_class = ConstantPoolIndex::new(this_class);
41 let super_class = reader.take::<u16>()?;
42 let super_class = ConstantPoolIndex::new(super_class);
43
44 let interfaces_count = reader.take::<u16>()?;
45 let mut interfaces = Vec::with_capacity(interfaces_count as usize);
46 for _ in 0..interfaces_count {
47 let interface = read_interface(reader, cp)?;
48 interfaces.push(interface);
49 }
50
51 let fields_count = reader.take::<u16>()?;
52 let mut fields = Vec::with_capacity(fields_count as usize);
53 for _ in 0..fields_count {
54 let field = read_field(reader, cp)?;
55 fields.push(field);
56 }
57
58 let methods_count = reader.take::<u16>()?;
59 let mut methods = Vec::with_capacity(methods_count as usize);
60 for _ in 0..methods_count {
61 let method = read_method(reader, cp)?;
62 methods.push(method);
63 }
64
65 let attributes_count = reader.take::<u16>()?;
66 let mut attributes = Vec::with_capacity(attributes_count as usize);
67 for _ in 0..attributes_count {
68 let attribute = read_attribute(reader, cp)?;
69 attributes.push(attribute);
70 }
71
72 Ok(ClassFile {
73 magic_number,
74 version,
75 constant_pool_count,
76 constant_pool: cp.clone(),
77 access_flags,
78 this_class,
79 super_class,
80 interfaces_count,
81 interfaces,
82 fields_count,
83 fields,
84 methods_count,
85 methods,
86 attributes_count,
87 attributes,
88 })
89}
90
91pub fn read_interface(
92 reader: &mut BufferedReader,
93 _cp: &mut ConstantPool,
94) -> Result<Interface, BytecodeError> {
95 let name_index = reader.take::<u16>()?;
96
97 Ok(Interface {
98 name_index: ConstantPoolIndex::new(name_index),
99 })
100}
101
102pub fn read_field(
103 reader: &mut BufferedReader,
104 cp: &mut ConstantPool,
105) -> Result<Field, BytecodeError> {
106 let access_flags = reader.take::<u16>()?;
107 let Some(access_flags) = FieldAccessFlags::from_bits(access_flags) else {
108 return Err(BytecodeError::InvalidClassFile);
109 };
110
111 let name_index = reader.take::<u16>()?;
112 let Some(name) = cp.text_of(name_index.into()) else {
113 return Err(BytecodeError::InvalidClassFile);
114 };
115
116 let descriptor_index = reader.take::<u16>()?;
117 let Some(descriptor) = cp.text_of(descriptor_index.into()) else {
118 return Err(BytecodeError::InvalidClassFile);
119 };
120 let descriptor = Descriptor::parse_from_field(descriptor).unwrap_or(Descriptor {
121 kind: DescriptorKind::Type,
122 ty: FieldType::Base(BaseType::Void),
123 });
124
125 let attributes_count = reader.take::<u16>()?;
126 let mut attributes = Vec::with_capacity(attributes_count as usize);
127 for _ in 0..attributes_count {
128 let attribute = read_attribute(reader, cp)?;
129 attributes.push(attribute);
130 }
131
132 Ok(Field {
133 name,
134 descriptor,
135 access_flags,
136 attributes,
137 })
138}
139
140pub fn read_method(
141 reader: &mut BufferedReader,
142 cp: &mut ConstantPool,
143) -> Result<Method, BytecodeError> {
144 let access_flags = reader.take::<u16>()?;
145 let Some(access_flags) = MethodAccessFlags::from_bits(access_flags) else {
146 return Err(BytecodeError::InvalidClassFile);
147 };
148
149 let name_index = reader.take::<u16>()?;
150 let Some(name) = cp.text_of(name_index.into()) else {
151 return Err(BytecodeError::InvalidClassFile);
152 };
153
154 let descriptor_index = reader.take::<u16>()?;
155 let Some(descriptor) = cp.text_of(descriptor_index.into()) else {
156 return Err(BytecodeError::InvalidClassFile);
157 };
158 let descriptor = Descriptor::parse_from_method(descriptor);
159
160 let attributes_count = reader.take::<u16>()?;
161 let mut attributes = Vec::with_capacity(attributes_count as usize);
162 for _ in 0..attributes_count {
163 let attribute = read_attribute(reader, cp)?;
164 attributes.push(attribute);
165 }
166
167 Ok(Method {
168 access_flags,
169 name,
170 descriptor,
171 attributes,
172 })
173}