276 lines
7.8 KiB
Rust
276 lines
7.8 KiB
Rust
|
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)]
|
||
|
pub struct ConstantClassInfo {
|
||
|
pub name_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantFieldRefInfo {
|
||
|
pub class_index: u16,
|
||
|
pub name_and_type_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantMethodRefInfo {
|
||
|
pub class_index: u16,
|
||
|
pub name_and_type_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantInterfaceMethodRefInfo {
|
||
|
pub class_index: u16,
|
||
|
pub name_and_type_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantStringInfo {
|
||
|
pub string_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantIntegerInfo {
|
||
|
pub value: i32,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantFloatInfo {
|
||
|
pub value: f32,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantLongInfo {
|
||
|
pub value: u64,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantDoubleInfo {
|
||
|
pub value: f64,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantNameAndTypeInfo {
|
||
|
pub name_index: u16,
|
||
|
pub descriptor_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantUtf8Info {
|
||
|
pub utf8: String
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
#[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<u8> for ConstantMethodHandleType {
|
||
|
type Error = Error;
|
||
|
|
||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||
|
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)]
|
||
|
pub struct ConstantMethodHandleInfo {
|
||
|
reference_kind: ConstantMethodHandleType,
|
||
|
reference_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantMethodTypeInfo {
|
||
|
descriptor_index: u16,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct ConstantInvokeDynamicInfo {
|
||
|
bootstrap_method_attr_index: u16,
|
||
|
name_and_type_index: u16,
|
||
|
}
|
||
|
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
#[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<Self, Error> {
|
||
|
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!()
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|