rjvm 0.3.0

Parse JVM class files with Rust
Documentation
use crate::bytecode::pool::{ConstantPool, ConstantPoolEntry, ConstantPoolIndex, ConstantTag};
use crate::bytecode::reader::BufferedReader;
use crate::bytecode::BytecodeError;

pub fn read_constant_pool_entry(
    reader: &mut BufferedReader,
    _cp: &mut ConstantPool,
) -> Result<ConstantPoolEntry, BytecodeError> {
    let tag = reader.take::<u8>()?;
    let Some(tag) = ConstantTag::from_tag(tag) else {
        return Err(BytecodeError::InvalidData);
    };

    let entry = match tag {
        ConstantTag::Class => {
            let name_index = reader.take::<u16>()?;

            ConstantPoolEntry::Class {
                name_index: ConstantPoolIndex::new(name_index),
            }
        }
        ConstantTag::FieldRef => {
            let class_index = reader.take::<u16>()?;
            let name_and_type_index = reader.take::<u16>()?;

            ConstantPoolEntry::FieldRef {
                class_index: ConstantPoolIndex::new(class_index),
                name_and_type_index: ConstantPoolIndex::new(name_and_type_index),
            }
        }
        ConstantTag::MethodRef => {
            let class_index = reader.take::<u16>()?;
            let name_and_type_index = reader.take::<u16>()?;

            ConstantPoolEntry::MethodRef {
                class_index: ConstantPoolIndex::new(class_index),
                name_and_type_index: ConstantPoolIndex::new(name_and_type_index),
            }
        }
        ConstantTag::InterfaceMethodRef => {
            let class_index = reader.take::<u16>()?;
            let name_and_type_index = reader.take::<u16>()?;

            ConstantPoolEntry::InterfaceMethodRef {
                class_index: ConstantPoolIndex::new(class_index),
                name_and_type_index: ConstantPoolIndex::new(name_and_type_index),
            }
        }
        ConstantTag::String => {
            let string_index = reader.take::<u16>()?;

            ConstantPoolEntry::String {
                string_index: ConstantPoolIndex::new(string_index),
            }
        }
        ConstantTag::Integer => {
            let bytes = reader.take::<i32>()?;

            ConstantPoolEntry::Integer { bytes }
        }
        ConstantTag::Float => {
            let bytes = reader.take::<f32>().expect("msg");

            ConstantPoolEntry::Float { bytes }
        }
        ConstantTag::Long => {
            let high_bytes = reader.take::<u32>()?;
            let low_bytes = reader.take::<u32>()?;

            ConstantPoolEntry::Long {
                high_bytes,
                low_bytes,
            }
        }
        ConstantTag::Double => {
            let high_bytes = reader.take::<u32>()?;
            let low_bytes = reader.take::<u32>()?;

            ConstantPoolEntry::Double {
                high_bytes,
                low_bytes,
            }
        }
        ConstantTag::NameAndType => {
            let name_index = reader.take::<u16>()?;
            let descriptor_index = reader.take::<u16>()?;

            ConstantPoolEntry::NameAndType {
                name_index: ConstantPoolIndex::new(name_index),
                descriptor_index: ConstantPoolIndex::new(descriptor_index),
            }
        }
        ConstantTag::Utf8 => {
            let length = reader.take::<u16>()?;
            let bytes = reader.take_bytes(length as usize)?;

            ConstantPoolEntry::Utf8 {
                length,
                bytes: bytes.to_vec(),
            }
        }
        ConstantTag::MethodHandle => {
            let reference_kind = reader.take::<u8>()?;
            let reference_index = reader.take::<u16>()?;

            ConstantPoolEntry::MethodHandle {
                reference_kind,
                reference_index: ConstantPoolIndex::new(reference_index),
            }
        }
        ConstantTag::MethodType => {
            let descriptor_index = reader.take::<u16>()?;

            ConstantPoolEntry::MethodType {
                descriptor_index: ConstantPoolIndex::new(descriptor_index),
            }
        }
        ConstantTag::Dynamic => {
            let bootstrap_method_attr_index = reader.take::<u16>()?;
            let name_and_type_index = reader.take::<u16>()?;

            ConstantPoolEntry::Dynamic {
                bootstrap_method_attr_index: ConstantPoolIndex::new(bootstrap_method_attr_index),
                name_and_type_index: ConstantPoolIndex::new(name_and_type_index),
            }
        }
        ConstantTag::InvokeDynamic => {
            let bootstrap_method_attr_index = reader.take::<u16>()?;
            let name_and_type_index = reader.take::<u16>()?;

            ConstantPoolEntry::InvokeDynamic {
                bootstrap_method_attr_index: ConstantPoolIndex::new(bootstrap_method_attr_index),
                name_and_type_index: ConstantPoolIndex::new(name_and_type_index),
            }
        }
        ConstantTag::Module => {
            let name_index = reader.take::<u16>()?;

            ConstantPoolEntry::Module {
                name_index: ConstantPoolIndex::new(name_index),
            }
        }
        ConstantTag::Package => {
            let name_index = reader.take::<u16>()?;

            ConstantPoolEntry::Package {
                name_index: ConstantPoolIndex::new(name_index),
            }
        }
    };

    Ok(entry)
}