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 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}