java.rs/src/class.rs
2023-10-02 16:03:51 +02:00

272 lines
6.4 KiB
Rust

use std::cell::{RefCell, UnsafeCell};
use crate::classloader::CpEntry;
use crate::heap::Object;
use anyhow::{anyhow, Error};
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use crate::io::read_u16;
#[derive(Debug)]
//TODO create factory function
pub struct Class {
pub minor_version: u16,
pub major_version: u16,
pub constant_pool: Rc<HashMap<u16, CpEntry>>,
pub access_flags: u16,
pub this_class: u16,
pub super_class: u16,
pub interfaces: Vec<u16>,
pub fields: Vec<Field>,
pub methods: HashMap<String, Method>,
pub attributes: HashMap<String, AttributeType>,
}
impl Class {
pub fn get_version(&self) -> (u16, u16) {
(self.major_version, self.minor_version)
}
pub fn get_method(&self, name: &str) -> Result<&Method, Error> {
self.methods
.get(name)
.ok_or(anyhow!("Method {} not found", name))
}
pub fn get_name(&self) -> &str {
if let CpEntry::ClassRef(name_index ) = self.constant_pool.get(&self.this_class).unwrap(){
if let CpEntry::Utf8(name) = self.constant_pool.get(name_index).unwrap(){
return name;
}
}
panic!();
}
}
unsafe impl Send for Class {}
unsafe impl Sync for Class {}
pub struct Method {
pub(crate) constant_pool: Rc<HashMap<u16, CpEntry>>,
access_flags: u16,
name_index: u16,
descriptor_index: u16,
pub(crate) attributes: HashMap<String, AttributeType>,
}
impl fmt::Debug for Method {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Method {{access_flags: {}, name_index: {}, descriptor_index: {}, attributes: {:?} }}",
self.access_flags, self.name_index, self.descriptor_index, self.attributes
)
}
}
impl Method {
pub fn new(
constant_pool: Rc<HashMap<u16, CpEntry>>,
access_flags: u16,
name_index: u16,
descriptor_index: u16,
attributes: HashMap<String, AttributeType>,
) -> Self {
Method {
constant_pool,
access_flags,
name_index,
descriptor_index,
attributes,
}
}
pub fn name(&self) -> String {
let mut full_name = String::new();
if let CpEntry::Utf8(s) = &self.constant_pool.get(&self.name_index).unwrap() {
full_name.push_str(s);
}
if let CpEntry::Utf8(s) = &self.constant_pool.get(&self.descriptor_index).unwrap() {
full_name.push_str(s);
}
full_name
}
}
pub struct Field {
constant_pool: Rc<HashMap<u16, CpEntry>>,
access_flags: u16,
pub(crate) name_index: u16,
descriptor_index: u16,
attributes: HashMap<String, AttributeType>,
}
impl fmt::Debug for Field {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Field {{access_flags: {}, name_index: {}, descriptor_index: {}, attributes: {:?} }}",
self.access_flags, self.name_index, self.descriptor_index, self.attributes
)
}
}
impl Field {
pub fn new(
constant_pool: Rc<HashMap<u16, CpEntry>>,
access_flags: u16,
name_index: u16,
descriptor_index: u16,
attributes: HashMap<String, AttributeType>,
) -> Self {
Field {
constant_pool,
access_flags,
name_index,
descriptor_index,
attributes,
}
}
pub fn name(&self) -> String {
let mut name = String::new();
name.push(' ');
if let CpEntry::Utf8(s) = &self.constant_pool.get(&self.name_index).unwrap() {
name.push_str(s);
}
name
}
pub fn type_of(&self) -> &String {
if let CpEntry::Utf8(s) = &self.constant_pool.get(&self.descriptor_index).unwrap() {
return s;
}
panic!()
}
}
const MODIFIERS: [(u16, &str); 12] = [
(0x0001, "public "),
(0x0002, "private "),
(0x0004, "protected "),
(0x0008, "static "),
(0x0010, "final "),
(0x0020, "synchronized "),
(0x0040, "volatile "),
(0x0080, "transient "),
(0x0100, "native "),
(0x0200, "interface "),
(0x0400, "interface "),
(0x0800, "strict "),
];
pub fn get_modifier(modifier: u16) -> String {
let mut output = String::new();
for m in MODIFIERS {
if modifier & m.0 == m.0 {
output.push_str(m.1)
}
}
output
}
#[derive(Debug)]
pub enum AttributeType {
ConstantValue(u16),
Code(MethodCode),
StackMapTable,
BootstrapMethods,
NestHost,
NestMembers,
PermittedSubclasses,
Exceptions,
InnerClasses,
EnclosingMethod,
Synthetic,
Signature,
Record,
SourceFile,
LineNumberTable,
LocalVariableTable,
LocalVariableTypeTable,
SourceDebugExtension,
Deprecated,
RuntimeVisibleAnnotations,
RuntimeInvisibleAnnotations,
RuntimeVisibleParameterAnnotations,
RuntimeInvisibleParameterAnnotations,
RuntimeVisibleTypeAnnotations,
RuntimeInvisibleTypeAnnotations,
AnnotationDefault,
MethodParameters,
Module,
ModulePackages,
ModuleMainClass,
}
#[derive(Debug)]
pub struct Exception {
pub start_pc: u16,
pub end_pc: u16,
pub handler_pc: u16,
pub catch_type: u16,
}
impl Exception {
pub fn read(code: &[u8], index: &mut usize) -> Self {
Self {
start_pc: read_u16(code, index),
end_pc: read_u16(code, index),
handler_pc: read_u16(code, index),
catch_type: read_u16(code, index),
}
}
}
#[derive(Debug)]
pub struct MethodCode {
_max_stack: u16,
_max_locals: u16,
pub(crate) opcodes: Vec<u8>,
_exception_table: Vec<Exception>,
_code_attributes: HashMap<String, AttributeType>,
}
impl MethodCode {
pub(crate) fn new(
_max_stack: u16,
_max_locals: u16,
code: Vec<u8>,
_exception_table: Vec<Exception>,
_code_attributes: HashMap<String, AttributeType>,
) -> Self {
Self {
_max_stack,
_max_locals,
opcodes: code,
_exception_table,
_code_attributes,
}
}
}
#[derive(Debug)]
pub enum Value {
Void,
Null,
// the $1_000_000 mistake
I32(i32),
I64(i64),
F32(f32),
F64(f64),
BOOL(bool),
CHAR(char),
Ref(Arc<UnsafeCell<Object>>),
}
unsafe impl Send for Value {}
unsafe impl Sync for Value {}