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<'a> ClassAttribute {
95 pub(crate) fn read(
96 pool: &ConstantPool,
97 cursor: &mut ByteCursor<'a>,
98 ) -> Result<Self, ClassFormatErr> {
99 let attr_name_idx = cursor.u16()?;
100 let _attribute_length = cursor.u32()? as usize;
101
102 let attribute_kind = AttributeKind::try_from(pool.get_utf8(&attr_name_idx)?)?;
103 match attribute_kind {
104 AttributeKind::SourceFile => Ok(ClassAttribute::SourceFile {
105 attr_name_idx,
106 sourcefile_idx: cursor.u16()?,
107 }),
108 AttributeKind::BootstrapMethods => {
109 let number_of_bootstrap_methods = cursor.u16()? as usize;
110 let mut bootstrap_methods = Vec::with_capacity(number_of_bootstrap_methods);
111 for _ in 0..number_of_bootstrap_methods {
112 let bootstrap_method_ref = cursor.u16()?;
113 let number_of_bootstrap_arguments = cursor.u16()? as usize;
114 let mut bootstrap_arguments = Vec::with_capacity(number_of_bootstrap_arguments);
115 for _ in 0..number_of_bootstrap_arguments {
116 bootstrap_arguments.push(cursor.u16()?);
117 }
118 bootstrap_methods.push(BootstrapMethodEntry::new(
119 bootstrap_method_ref,
120 bootstrap_arguments,
121 ));
122 }
123 Ok(ClassAttribute::BootstrapMethods {
124 attr_name_idx,
125 bootstrap_methods,
126 })
127 }
128 AttributeKind::InnerClasses => {
129 let number_of_classes = cursor.u16()? as usize;
130 let mut classes = Vec::with_capacity(number_of_classes);
131 for _ in 0..number_of_classes {
132 classes.push(InnerClassEntry::new(
133 cursor.u16()?,
134 cursor.u16()?,
135 cursor.u16()?,
136 cursor.u16()?,
137 ));
138 }
139 Ok(ClassAttribute::InnerClasses {
140 attr_name_idx,
141 classes,
142 })
143 }
144 AttributeKind::NestMembers => {
145 let number_of_classes = cursor.u16()? as usize;
146 let mut classes = Vec::with_capacity(number_of_classes);
147 for _ in 0..number_of_classes {
148 classes.push(cursor.u16()?);
149 }
150 Ok(ClassAttribute::NestMembers {
151 attr_name_idx,
152 classes,
153 })
154 }
155 AttributeKind::NestHost => {
156 let host_class_idx = cursor.u16()?;
157 Ok(ClassAttribute::NestHost {
158 attr_name_idx,
159 host_class_idx,
160 })
161 }
162 AttributeKind::EnclosingMethod => {
163 let class_idx = cursor.u16()?;
164 let method_idx = cursor.u16()?;
165 Ok(ClassAttribute::EnclosingMethod {
166 attr_name_idx,
167 class_idx,
168 method_idx,
169 })
170 }
171 AttributeKind::PermittedSubclasses => {
172 let number_of_classes = cursor.u16()? as usize;
173 let mut classes = Vec::with_capacity(number_of_classes);
174 for _ in 0..number_of_classes {
175 classes.push(cursor.u16()?);
176 }
177 Ok(ClassAttribute::PermittedSubclasses {
178 attr_name_idx,
179 classes,
180 })
181 }
182 AttributeKind::RuntimeVisibleAnnotations
183 | AttributeKind::RuntimeVisibleTypeAnnotations
184 | AttributeKind::RuntimeInvisibleTypeAnnotations
185 | AttributeKind::Synthetic
186 | AttributeKind::Deprecated
187 | AttributeKind::RuntimeInvisibleAnnotations
188 | AttributeKind::Signature => Ok(ClassAttribute::Shared(SharedAttribute::read(
189 attr_name_idx,
190 attribute_kind,
191 cursor,
192 )?)),
193 other => unimplemented!("Class attribute {:?} not implemented", other),
194 }
195 }
196}