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#[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#[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!() }
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}