Skip to main content

lvm_class/attribute/
class.rs

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}