use std::io::Read; use crate::classfile::Error; use crate::classfile::{read_u16, read_u8, read_f32, read_f64, read_u64, read_i32}; #[derive(Debug, Copy, Clone)] pub struct ConstantClassInfo { pub name_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantFieldRefInfo { pub class_index: u16, pub name_and_type_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantMethodRefInfo { pub class_index: u16, pub name_and_type_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantInterfaceMethodRefInfo { pub class_index: u16, pub name_and_type_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantStringInfo { pub string_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantIntegerInfo { pub value: i32, } #[derive(Debug, Copy, Clone)] pub struct ConstantFloatInfo { pub value: f32, } #[derive(Debug, Copy, Clone)] pub struct ConstantLongInfo { pub value: u64, } #[derive(Debug, Copy, Clone)] pub struct ConstantDoubleInfo { pub value: f64, } #[derive(Debug, Copy, Clone)] pub struct ConstantNameAndTypeInfo { pub name_index: u16, pub descriptor_index: u16, } #[derive(Debug, Clone)] pub struct ConstantUtf8Info { pub utf8: String } #[derive(Debug, Copy, Clone)] #[repr(u8)] pub enum ConstantMethodHandleType { RefGetField(u8) = 1, RefGetStatic(u8) = 2, RefPutField(u8) = 3, RefPutStatic(u8) = 4, RefInvokeVirtual(u8) = 5, RefInvokeStatic(u8) = 6, RefInvokeSpecial(u8) = 7, RefNewInvokeSpecial(u8) = 8, RefInvokeInterface(u8) = 9, } impl TryFrom for ConstantMethodHandleType { type Error = Error; fn try_from(value: u8) -> Result { return match value { 1 => Ok(Self::RefGetField(value)), 2 => Ok(Self::RefGetStatic(value)), 3 => Ok(Self::RefPutField(value)), 4 => Ok(Self::RefPutStatic(value)), 5 => Ok(Self::RefInvokeVirtual(value)), 6 => Ok(Self::RefInvokeStatic(value)), 7 => Ok(Self::RefInvokeSpecial(value)), 8 => Ok(Self::RefNewInvokeSpecial(value)), 9 => Ok(Self::RefInvokeInterface(value)), _ => Err( Error::BadEnumError(format!("Unexpected MethodHandleType: {}", value)) ), } } } #[derive(Debug, Copy, Clone)] pub struct ConstantMethodHandleInfo { reference_kind: ConstantMethodHandleType, reference_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantMethodTypeInfo { descriptor_index: u16, } #[derive(Debug, Copy, Clone)] pub struct ConstantInvokeDynamicInfo { bootstrap_method_attr_index: u16, name_and_type_index: u16, } #[derive(Debug, Clone)] #[repr(u8)] pub enum ConstantPoolInfo { Class(ConstantClassInfo) = 7, FieldRef(ConstantFieldRefInfo) = 9, MethodRef(ConstantMethodRefInfo) = 10, InterfaceMethodRef(ConstantInterfaceMethodRefInfo) = 11, String(ConstantStringInfo) = 8, Integer(ConstantIntegerInfo) = 3, Float(ConstantFloatInfo) = 4, Long(ConstantLongInfo) = 5, Double(ConstantDoubleInfo) = 6, NameAndType(ConstantNameAndTypeInfo) = 12, Utf8(ConstantUtf8Info) = 1, MethodHandle(ConstantMethodHandleInfo) = 15, MethodType(ConstantMethodTypeInfo) = 16, InvokeDynamic(ConstantInvokeDynamicInfo) = 18, Nothing() = 255, } impl ConstantPoolInfo { pub fn from_reader(reader: &mut dyn Read) -> Result { let tag = read_u8(reader)?; Ok( match tag { 1 => { ConstantPoolInfo::Utf8( ConstantUtf8Info { utf8: { let length = read_u16(reader)?; let mut buffer: Box<[u8]> = vec![0; length.into()].into_boxed_slice(); reader.read_exact(&mut buffer)?; std::str::from_utf8(&buffer)?.to_string() } } ) } 3 => { ConstantPoolInfo::Integer( ConstantIntegerInfo { value: read_i32(reader)? } ) } 4 => { ConstantPoolInfo::Float( ConstantFloatInfo { value: read_f32(reader)? } ) } 5 => { ConstantPoolInfo::Long( ConstantLongInfo { value: read_u64(reader)? } ) } 6 => { ConstantPoolInfo::Double( ConstantDoubleInfo { value: read_f64(reader)? } ) } 7 => { ConstantPoolInfo::Class( ConstantClassInfo { name_index: read_u16(reader)? } ) } 8 => { ConstantPoolInfo::String( ConstantStringInfo { string_index: read_u16(reader)? } ) } 9 => { ConstantPoolInfo::FieldRef( ConstantFieldRefInfo { class_index: read_u16(reader)?, name_and_type_index: read_u16(reader)? } ) } 10 => { ConstantPoolInfo::MethodRef( ConstantMethodRefInfo { class_index: read_u16(reader)?, name_and_type_index: read_u16(reader)? } ) } 11 => { ConstantPoolInfo::InterfaceMethodRef( ConstantInterfaceMethodRefInfo { class_index: read_u16(reader)?, name_and_type_index: read_u16(reader)? } ) } 12 => { ConstantPoolInfo::NameAndType( ConstantNameAndTypeInfo { name_index: read_u16(reader)?, descriptor_index: read_u16(reader)? } ) } 15 => { ConstantPoolInfo::MethodHandle( ConstantMethodHandleInfo { reference_kind: ConstantMethodHandleType::try_from(read_u8(reader)?)?, reference_index: read_u16(reader)?, } ) } 16 => { ConstantPoolInfo::MethodType( ConstantMethodTypeInfo { descriptor_index: read_u16(reader)?, } ) } 18 => { ConstantPoolInfo::InvokeDynamic( ConstantInvokeDynamicInfo { bootstrap_method_attr_index: read_u16(reader)?, name_and_type_index: read_u16(reader)?, } ) } _ => unreachable!() } ) } }