Skip to main content

lvm_class/constant_pool/
entry.rs

1use crate::constant_pool::types::{Dynamic, MethodHandle, NameAndType, Reference};
2use crate::error::ClassFormatErr;
3use lvm_common::utils::cursor::ByteCursor;
4use num_enum::TryFromPrimitive;
5use std::fmt::{Display, Formatter};
6
7/// Tag identifying the type of a constant pool entry.
8///
9/// https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4-210
10/// Table 4.4-B. Constant pool tags (by tag)
11#[derive(Debug, Clone, PartialEq, Eq, TryFromPrimitive)]
12#[repr(u8)]
13pub enum ConstantKind {
14    Unused = 0,
15    Utf8 = 1,
16    Integer = 3,
17    Float = 4,
18    Long = 5,
19    Double = 6,
20    Class = 7,
21    String = 8,
22    FieldRef = 9,
23    MethodRef = 10,
24    InterfaceMethodRef = 11,
25    NameAndType = 12,
26    MethodHandle = 15,
27    MethodType = 16,
28    Dynamic = 17,
29    InvokeDynamic = 18,
30    Module = 19,
31    Package = 20,
32}
33
34impl Display for ConstantKind {
35    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36        let s = match self {
37            ConstantKind::Unused => "Unused",
38            ConstantKind::Utf8 => "Utf8",
39            ConstantKind::Integer => "Integer",
40            ConstantKind::Float => "Float",
41            ConstantKind::Long => "Long",
42            ConstantKind::Double => "Double",
43            ConstantKind::Class => "Class",
44            ConstantKind::String => "String",
45            ConstantKind::FieldRef => "Fieldref",
46            ConstantKind::MethodRef => "Methodref",
47            ConstantKind::InterfaceMethodRef => "InterfaceMethodref",
48            ConstantKind::NameAndType => "NameAndType",
49            ConstantKind::MethodHandle => "MethodHandle",
50            ConstantKind::MethodType => "MethodType",
51            ConstantKind::Dynamic => "Dynamic",
52            ConstantKind::InvokeDynamic => "InvokeDynamic",
53            ConstantKind::Module => "Module",
54            ConstantKind::Package => "Package",
55        };
56        f.pad(s)
57    }
58}
59
60/// A single entry in the constant pool.
61///
62/// https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4-140
63/// Each entry is as described in section column of Table 4.4-A. Constant pool tags (by section)
64#[derive(Debug, Clone, PartialEq)]
65pub enum ConstantEntry {
66    Unused,
67    Utf8(String),
68    Integer(i32),
69    Float(f32),
70    Long(i64),
71    Double(f64),
72    Class(u16),
73    String(u16),
74    MethodRef(Reference),
75    FieldRef(Reference),
76    InterfaceMethodRef(Reference),
77    NameAndType(NameAndType),
78    Dynamic(Dynamic),
79    InvokeDynamic(Dynamic),
80    MethodHandle(MethodHandle),
81    MethodType(u16),
82}
83
84impl<'a> ConstantEntry {
85    pub(crate) fn read(cursor: &mut ByteCursor<'a>) -> Result<Self, ClassFormatErr> {
86        let raw_tag = cursor.u8()?;
87        let tag = ConstantKind::try_from_primitive(raw_tag)
88            .map_err(|_| ClassFormatErr::UnknownTag(raw_tag))?;
89        let const_info = match tag {
90            ConstantKind::Unused => {
91                unreachable!() // TODO: Sure?
92            }
93            ConstantKind::Utf8 => {
94                let len = cursor.u16()?;
95                let bytes = cursor.bytes(len as usize)?;
96                Self::Utf8(String::from_utf8_lossy(bytes).to_string())
97            }
98            ConstantKind::Integer => {
99                let value = cursor.i32()?;
100                Self::Integer(value)
101            }
102            ConstantKind::Float => {
103                let value = cursor.f32()?;
104                Self::Float(value)
105            }
106            ConstantKind::Long => {
107                let value = cursor.i64()?;
108                Self::Long(value)
109            }
110            ConstantKind::Double => {
111                let value = cursor.f64()?;
112                Self::Double(value)
113            }
114            ConstantKind::Class => Self::Class(cursor.u16()?),
115            ConstantKind::String => Self::String(cursor.u16()?),
116            ConstantKind::FieldRef => Self::FieldRef(Reference::new(cursor.u16()?, cursor.u16()?)),
117            ConstantKind::MethodRef => {
118                Self::MethodRef(Reference::new(cursor.u16()?, cursor.u16()?))
119            }
120            ConstantKind::InterfaceMethodRef => {
121                Self::InterfaceMethodRef(Reference::new(cursor.u16()?, cursor.u16()?))
122            }
123            ConstantKind::NameAndType => {
124                Self::NameAndType(NameAndType::new(cursor.u16()?, cursor.u16()?))
125            }
126            ConstantKind::Dynamic => Self::Dynamic(Dynamic::new(cursor.u16()?, cursor.u16()?)),
127            ConstantKind::InvokeDynamic => {
128                Self::InvokeDynamic(Dynamic::new(cursor.u16()?, cursor.u16()?))
129            }
130            ConstantKind::Module => todo!(),
131            ConstantKind::Package => todo!(),
132            ConstantKind::MethodHandle => {
133                Self::MethodHandle(MethodHandle::new(cursor.u8()?, cursor.u16()?))
134            }
135            ConstantKind::MethodType => Self::MethodType(cursor.u16()?),
136        };
137        Ok(const_info)
138    }
139
140    pub fn get_kind(&self) -> ConstantKind {
141        match self {
142            ConstantEntry::Unused => ConstantKind::Unused,
143            ConstantEntry::Utf8(_) => ConstantKind::Utf8,
144            ConstantEntry::Integer(_) => ConstantKind::Integer,
145            ConstantEntry::Float(_) => ConstantKind::Float,
146            ConstantEntry::Long(_) => ConstantKind::Long,
147            ConstantEntry::Double(_) => ConstantKind::Double,
148            ConstantEntry::Class(_) => ConstantKind::Class,
149            ConstantEntry::String(_) => ConstantKind::String,
150            ConstantEntry::MethodRef(_) => ConstantKind::MethodRef,
151            ConstantEntry::FieldRef(_) => ConstantKind::FieldRef,
152            ConstantEntry::InterfaceMethodRef(_) => ConstantKind::InterfaceMethodRef,
153            ConstantEntry::NameAndType(_) => ConstantKind::NameAndType,
154            ConstantEntry::Dynamic(_) => ConstantKind::Dynamic,
155            ConstantEntry::InvokeDynamic(_) => ConstantKind::InvokeDynamic,
156            ConstantEntry::MethodHandle(_) => ConstantKind::MethodHandle,
157            ConstantEntry::MethodType(_) => ConstantKind::MethodType,
158        }
159    }
160}