1use crate::ClassFormatErr;
2use crate::attribute::{AttributeKind, SharedAttribute};
3use crate::constant_pool::ConstantPool;
4use lvm_common::utils::cursor::ByteCursor;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum ClassAttribute {
8 Shared(SharedAttribute),
9 SourceFile {
10 attr_name_idx: u16,
11 sourcefile_idx: u16,
12 },
13 InnerClasses {
14 attr_name_idx: u16,
15 classes: Vec<InnerClassEntry>,
16 },
17 EnclosingMethod {
18 attr_name_idx: u16,
19 class_idx: u16,
20 method_idx: u16,
21 },
22 SourceDebugExtension {
23 attr_name_idx: u16,
24 },
25 BootstrapMethods {
26 attr_name_idx: u16,
27 bootstrap_methods: Vec<BootstrapMethodEntry>,
28 },
29 Module {
30 attr_name_idx: u16,
31 },
32 ModulePackages {
33 attr_name_idx: u16,
34 },
35 ModuleMainClass {
36 attr_name_idx: u16,
37 },
38 NestHost {
39 attr_name_idx: u16,
40 host_class_idx: u16,
41 },
42 NestMembers {
43 attr_name_idx: u16,
44 classes: Vec<u16>,
45 },
46 Record {
47 attr_name_idx: u16,
48 },
49 PermittedSubclasses {
50 attr_name_idx: u16,
51 classes: Vec<u16>,
52 },
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct BootstrapMethodEntry {
57 pub bootstrap_method_idx: u16,
58 pub bootstrap_arguments: Vec<u16>,
59}
60
61impl BootstrapMethodEntry {
62 pub(crate) fn new(bootstrap_method_ref: u16, bootstrap_arguments: Vec<u16>) -> Self {
63 Self {
64 bootstrap_method_idx: bootstrap_method_ref,
65 bootstrap_arguments,
66 }
67 }
68}
69
70#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct InnerClassEntry {
72 pub inner_class_info_index: u16,
73 pub outer_class_info_index: u16,
74 pub inner_name_index: u16,
75 pub inner_class_access_flags: u16,
76}
77
78impl InnerClassEntry {
79 pub(crate) fn new(
80 inner_class_info_index: u16,
81 outer_class_info_index: u16,
82 inner_name_index: u16,
83 inner_class_access_flags: u16,
84 ) -> Self {
85 Self {
86 inner_class_info_index,
87 outer_class_info_index,
88 inner_name_index,
89 inner_class_access_flags,
90 }
91 }
92}
93
94impl ClassAttribute {
95 pub fn kind(&self) -> AttributeKind {
96 match self {
97 Self::Shared(attr) => attr.kind(),
98 Self::SourceFile { .. } => AttributeKind::SourceFile,
99 Self::InnerClasses { .. } => AttributeKind::InnerClasses,
100 Self::EnclosingMethod { .. } => AttributeKind::EnclosingMethod,
101 Self::SourceDebugExtension { .. } => AttributeKind::SourceDebugExtension,
102 Self::BootstrapMethods { .. } => AttributeKind::BootstrapMethods,
103 Self::Module { .. } => AttributeKind::Module,
104 Self::ModulePackages { .. } => AttributeKind::ModulePackages,
105 Self::ModuleMainClass { .. } => AttributeKind::ModuleMainClass,
106 Self::NestHost { .. } => AttributeKind::NestHost,
107 Self::NestMembers { .. } => AttributeKind::NestMembers,
108 Self::Record { .. } => AttributeKind::Record,
109 Self::PermittedSubclasses { .. } => AttributeKind::PermittedSubclasses,
110 }
111 }
112}
113
114impl<'a> ClassAttribute {
115 pub(crate) fn read(
116 pool: &ConstantPool,
117 cursor: &mut ByteCursor<'a>,
118 ) -> Result<Self, ClassFormatErr> {
119 let attr_name_idx = cursor.u16()?;
120 let _attribute_length = cursor.u32()? as usize;
121
122 let attribute_kind = AttributeKind::try_from(pool.get_utf8(&attr_name_idx)?)?;
123 match attribute_kind {
124 AttributeKind::SourceFile => Ok(ClassAttribute::SourceFile {
125 attr_name_idx,
126 sourcefile_idx: cursor.u16()?,
127 }),
128 AttributeKind::BootstrapMethods => {
129 let number_of_bootstrap_methods = cursor.u16()? as usize;
130 let mut bootstrap_methods = Vec::with_capacity(number_of_bootstrap_methods);
131 for _ in 0..number_of_bootstrap_methods {
132 let bootstrap_method_ref = cursor.u16()?;
133 let number_of_bootstrap_arguments = cursor.u16()? as usize;
134 let mut bootstrap_arguments = Vec::with_capacity(number_of_bootstrap_arguments);
135 for _ in 0..number_of_bootstrap_arguments {
136 bootstrap_arguments.push(cursor.u16()?);
137 }
138 bootstrap_methods.push(BootstrapMethodEntry::new(
139 bootstrap_method_ref,
140 bootstrap_arguments,
141 ));
142 }
143 Ok(ClassAttribute::BootstrapMethods {
144 attr_name_idx,
145 bootstrap_methods,
146 })
147 }
148 AttributeKind::InnerClasses => {
149 let number_of_classes = cursor.u16()? as usize;
150 let mut classes = Vec::with_capacity(number_of_classes);
151 for _ in 0..number_of_classes {
152 classes.push(InnerClassEntry::new(
153 cursor.u16()?,
154 cursor.u16()?,
155 cursor.u16()?,
156 cursor.u16()?,
157 ));
158 }
159 Ok(ClassAttribute::InnerClasses {
160 attr_name_idx,
161 classes,
162 })
163 }
164 AttributeKind::NestMembers => {
165 let number_of_classes = cursor.u16()? as usize;
166 let mut classes = Vec::with_capacity(number_of_classes);
167 for _ in 0..number_of_classes {
168 classes.push(cursor.u16()?);
169 }
170 Ok(ClassAttribute::NestMembers {
171 attr_name_idx,
172 classes,
173 })
174 }
175 AttributeKind::NestHost => {
176 let host_class_idx = cursor.u16()?;
177 Ok(ClassAttribute::NestHost {
178 attr_name_idx,
179 host_class_idx,
180 })
181 }
182 AttributeKind::EnclosingMethod => {
183 let class_idx = cursor.u16()?;
184 let method_idx = cursor.u16()?;
185 Ok(ClassAttribute::EnclosingMethod {
186 attr_name_idx,
187 class_idx,
188 method_idx,
189 })
190 }
191 AttributeKind::PermittedSubclasses => {
192 let number_of_classes = cursor.u16()? as usize;
193 let mut classes = Vec::with_capacity(number_of_classes);
194 for _ in 0..number_of_classes {
195 classes.push(cursor.u16()?);
196 }
197 Ok(ClassAttribute::PermittedSubclasses {
198 attr_name_idx,
199 classes,
200 })
201 }
202 AttributeKind::RuntimeVisibleAnnotations
203 | AttributeKind::RuntimeVisibleTypeAnnotations
204 | AttributeKind::RuntimeInvisibleTypeAnnotations
205 | AttributeKind::Synthetic
206 | AttributeKind::Deprecated
207 | AttributeKind::RuntimeInvisibleAnnotations
208 | AttributeKind::Signature => Ok(ClassAttribute::Shared(SharedAttribute::read(
209 attr_name_idx,
210 attribute_kind,
211 cursor,
212 )?)),
213 other => unimplemented!("Class attribute {:?} not implemented", other),
214 }
215 }
216}