1use crate::attribute::ClassAttribute;
6use crate::constant_pool::{ConstantEntry, ConstantPool};
7use crate::flags::ClassFlags;
8use crate::member::{FieldInfo, MethodInfo};
9use lvm_common::utils::cursor::ByteCursor;
10
11pub use crate::error::{ClassFormatErr, InstructionErr};
12
13pub mod attribute;
14pub mod bytecode;
15pub mod constant_pool;
16pub mod error;
17pub mod flags;
18pub mod member;
19pub mod prelude;
20pub mod verify;
21#[cfg(feature = "write")]
22pub mod write;
23#[derive(Debug)]
32pub struct ClassFile {
33 pub minor_version: u16,
34 pub major_version: u16,
35 pub cp: ConstantPool,
36 pub access_flags: ClassFlags,
37 pub this_class: u16,
38 pub super_class: u16,
39 pub interfaces: Vec<u16>,
40 pub fields: Vec<FieldInfo>,
41 pub methods: Vec<MethodInfo>,
42 pub attributes: Vec<ClassAttribute>,
43}
44
45impl ClassFile {
46 const MAGIC: u32 = 0xCAFEBABE;
47 fn validate_magic(val: u32) -> Result<(), ClassFormatErr> {
48 (val == ClassFile::MAGIC)
49 .then_some(())
50 .ok_or(ClassFormatErr::WrongMagic(val))
51 }
52
53 pub fn get_super_class_name(&self) -> Option<Result<&str, ClassFormatErr>> {
54 if self.super_class == 0 {
55 None
56 } else {
57 Some(self.cp.get_class_name(&self.super_class))
58 }
59 }
60}
61
62impl TryFrom<Vec<u8>> for ClassFile {
63 type Error = ClassFormatErr;
64
65 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
66 let mut cursor = ByteCursor::new(&value);
67 let magic = cursor.u32()?;
68 ClassFile::validate_magic(magic)?;
69 let minor_version = cursor.u16()?;
70 let major_version = cursor.u16()?;
71 let constant_pool_count = cursor.u16()?;
72 let mut constant_pool = Vec::with_capacity((constant_pool_count + 1) as usize);
73 constant_pool.push(ConstantEntry::Unused);
74 let mut i = 1;
75 while i < constant_pool_count {
76 let constant = ConstantEntry::read(&mut cursor)?;
77 constant_pool.push(constant.clone());
78 match constant {
79 ConstantEntry::Long(_) | ConstantEntry::Double(_) => {
82 constant_pool.push(ConstantEntry::Unused);
83 i += 2;
84 }
85 _ => {
86 i += 1;
87 }
88 }
89 }
90 let constant_pool = ConstantPool {
91 inner: constant_pool,
92 };
93
94 let access_flags = ClassFlags::new(cursor.u16()?);
95 let this_class = cursor.u16()?;
96 let super_class = cursor.u16()?;
97 let interfaces_count = cursor.u16()?;
98 let mut interfaces = Vec::with_capacity(interfaces_count as usize);
99 for _ in 0..interfaces_count {
100 interfaces.push(cursor.u16()?);
101 }
102 let fields_count = cursor.u16()?;
103 let mut fields = Vec::with_capacity(fields_count as usize);
104 for _ in 0..fields_count {
105 fields.push(FieldInfo::read(&constant_pool, &mut cursor)?);
106 }
107 let methods_count = cursor.u16()?;
108 let mut methods = Vec::with_capacity(methods_count as usize);
109 for _ in 0..methods_count {
110 methods.push(MethodInfo::read(&constant_pool, &mut cursor)?);
111 }
112 let attributes_count = cursor.u16()?;
113 let mut attributes = Vec::with_capacity(attributes_count as usize);
114 for _ in 0..attributes_count {
115 attributes.push(ClassAttribute::read(&constant_pool, &mut cursor)?);
116 }
117
118 if cursor.u8().is_ok() {
119 Err(ClassFormatErr::TrailingBytes)
120 } else {
121 Ok(Self {
122 minor_version,
123 major_version,
124 cp: constant_pool,
125 access_flags,
126 this_class,
127 super_class,
128 interfaces,
129 fields,
130 methods,
131 attributes,
132 })
133 }
134 }
135}