rjvm/bytecode/reader/
containers.rs

1use 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}