Somewhat recursive string construction

This commit is contained in:
VegOwOtenks 2024-09-05 00:33:14 +02:00
parent 4dabd6c3a8
commit 3c4921aa54
9 changed files with 1130 additions and 185 deletions

View file

@ -5,7 +5,7 @@ use core::str::Utf8Error;
use crate::accessmasks::*;
use crate::bytecode::Bytecode;
use crate::constantpool::{ ConstantPoolInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo };
use crate::constantpool::{ ConstantFieldRefInfo, ConstantPoolInfo, ConstantUtf8Info, ConstantStringInfo, ConstantMethodRefInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo, ConstantLongInfo };
#[derive(Debug)]
pub enum Error {
@ -217,6 +217,17 @@ impl JavaClassFile {
return Ok(methodref_entry);
}
pub fn pool_fieldref_entry(&self, index: u16) -> Result<&ConstantFieldRefInfo, Error> {
let pool_entry = self.pool_entry(index)?;
let fieldref_entry = match pool_entry {
ConstantPoolInfo::FieldRef(data) => data,
_ => unreachable!(),
};
return Ok(fieldref_entry);
}
pub fn pool_class_entry(&self, index: u16) -> Result<&ConstantClassInfo, Error> {
let pool_entry = self.pool_entry(index)?;
@ -235,6 +246,15 @@ impl JavaClassFile {
};
}
pub fn pool_long_entry(&self, index: u16) -> Result<&ConstantLongInfo, Error> {
let pool_entry = self.pool_entry(index)?;
return match pool_entry {
ConstantPoolInfo::Long(data) => Ok(data),
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type Long but found {:?}", index, self.get_classname()?, pool_entry)))
};
}
pub fn pool_int_entry(&self, index: u16) -> Result<&ConstantIntegerInfo, Error> {
let pool_entry = self.pool_entry(index)?;
@ -253,6 +273,47 @@ impl JavaClassFile {
};
}
pub fn pool_string_entry(&self, index: u16) -> Result<&ConstantStringInfo, Error> {
let pool_entry = self.pool_entry(index)?;
return match pool_entry {
ConstantPoolInfo::String(data) => Ok(data),
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type String but found {:?}", index, self.get_classname()?, pool_entry)))
};
}
pub fn gather_string(&self, index: u16) -> Result<&String, Error> {
let string = self.pool_string_entry(index)?;
return Ok(&(self.pool_utf8_entry(string.string_index)?.utf8));
}
pub fn gather_nameandtype(&self, index: u16) -> Result<(&String, &String), Error> {
let nameandtype = self.pool_nameandtype_entry(index)?;
let name = &self.pool_utf8_entry(nameandtype.name_index)?.utf8;
let descriptor = &self.pool_utf8_entry(nameandtype.descriptor_index)?.utf8;
Ok((name, descriptor))
}
pub fn gather_fieldref(&self, index: u16) -> Result<(&String, &String, &String), Error> {
let fieldref = self.pool_fieldref_entry(index)?;
let (field_name, field_descriptor) = self.gather_nameandtype(fieldref.name_and_type_index)?;
let class_name = self.gather_class(fieldref.class_index)?;
Ok((class_name, field_name, field_descriptor))
}
pub fn gather_class(&self, index: u16) -> Result<&String, Error> {
let class_entry = self.pool_class_entry(index)?;
let class_name_entry = self.pool_utf8_entry(class_entry.name_index)?;
let class_name = &class_name_entry.utf8;
Ok(class_name)
}
pub fn gather_methodref(&self, index: u16) -> Result<(&String, &String, &String), Error> {
let methodref = self.pool_methodref_entry(index)?;
let class_entry = self.pool_class_entry(methodref.class_index)?;
@ -671,7 +732,7 @@ impl ExceptionAttributeData {
}
#[repr(u8)]
#[derive(Debug, Eq, PartialEq, Clone)]
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum AbstractTypeKind {
Void() = b'V', // void
Byte() = b'B', // signed byte
@ -702,7 +763,7 @@ impl Into<String> for &AbstractTypeKind {
}
}
#[derive(Debug, Eq, PartialEq, Clone)]
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct AbstractTypeDescription {
pub array_level: u8,
pub kind: AbstractTypeKind,
@ -725,7 +786,7 @@ impl Into<String> for &AbstractTypeDescription {
}
impl AbstractTypeDescription {
fn parse_first(s: &str) -> Result<(usize, Self), Error> {
pub fn parse_first(s: &str) -> Result<(usize, Self), Error> {
let mut offset: usize = 0;
let arrays_parsed = s.trim_start_matches("[");
let array_level = (s.len() - arrays_parsed.len()).try_into();
@ -757,7 +818,7 @@ impl AbstractTypeDescription {
AbstractTypeKind::Classname(classname_string.to_string())
}
_ => return Err(Error::BadFileError(format!("Invalid Type character: '{}' in string \"{}\"", type_char, s))),
_ => return Err(Error::BadFileError(format!("Invalid Type character: '{}' in string '{}'", type_char, s))),
};
return Ok((offset, AbstractTypeDescription { array_level, kind }))
@ -809,13 +870,14 @@ impl TryFrom<&String> for MethodDescriptor {
s.get(total_offset..).unwrap()
.strip_prefix(")")
// unreachable?
.ok_or(Error::BadFileError(format!("Bad method descriptor")))?;
total_offset += 1;
let (offset, return_type) = AbstractTypeDescription::parse_first(s.get(total_offset..).unwrap())?;
if offset != s.get(total_offset..).unwrap().len() {
return Err(Error::BadFileError(format!("Trailing characters in method descriptor string: \"{}\"", s)))
return Err(Error::BadFileError(format!("Trailing characters in method descriptor string: '{}'", s)))
}
Ok(
@ -942,11 +1004,11 @@ pub fn read_i32(reader: &mut dyn Read) -> Result<i32, std::io::Error> {
return Ok(i32::from_be_bytes(buffer));
}
pub fn read_u64(reader: &mut dyn Read) -> Result<u64, std::io::Error> {
let high_bytes: u64 = read_u32(reader)?.into();
let low_bytes: u64 = read_u32(reader)?.into();
pub fn read_i64(reader: &mut dyn Read) -> Result<i64, std::io::Error> {
let mut buffer: [u8; 8] = [0; 8];
reader.read_exact(&mut buffer)?;
return Ok((high_bytes << 32) | low_bytes);
return Ok(i64::from_be_bytes(buffer));
}
pub fn read_u32(reader: &mut dyn Read) -> Result<u32, std::io::Error> {