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