mirror of
https://github.com/Noratrieb/coldsquare.git
synced 2026-01-17 01:45:09 +01:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
456087553a
5 changed files with 130 additions and 74 deletions
|
|
@ -8,4 +8,5 @@ my goal is not to make a fully working jvm that will run your spring application
|
||||||
it would be amazing if it even managed to run a hello world
|
it would be amazing if it even managed to run a hello world
|
||||||
|
|
||||||
## what i have for now:
|
## what i have for now:
|
||||||
* (Hopefully) working complete `.class` file parser
|
* Almost working complete `.class` file parser
|
||||||
|
* Primitive file info for `.class` files similar to `javap`
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use file_parser::{ClassFile, ParseErr};
|
use file_parser::ClassFile;
|
||||||
use std::error::Error;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dyn Error>> {
|
pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), io::Error> {
|
||||||
let cp = &class.constant_pool;
|
let cp = &class.constant_pool;
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
|
|
@ -17,24 +17,21 @@ pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dy
|
||||||
w,
|
w,
|
||||||
"class {} extends {}{} {{",
|
"class {} extends {}{} {{",
|
||||||
&class.this_class.get(cp).name_index.get(cp),
|
&class.this_class.get(cp).name_index.get(cp),
|
||||||
match class.super_class.get(cp) {
|
match class.super_class.maybe_get(cp) {
|
||||||
None => "<none>",
|
None => "<none>",
|
||||||
Some(class) => &class.name_index.get(cp),
|
Some(class) => class.name_index.get(cp),
|
||||||
}
|
},
|
||||||
if class.interfaces.is_empty() {
|
if class.interfaces.is_empty() {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!(
|
||||||
" implements {}",
|
" implements {}",
|
||||||
// this is absolutely terrible but it works i guess
|
|
||||||
class
|
class
|
||||||
.interfaces
|
.interfaces
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| i.get(cp))
|
.map(|i| i.get(cp))
|
||||||
.collect::<Result<Vec<_>, ParseErr>>()?
|
|
||||||
.iter()
|
|
||||||
.map(|i| i.name_index.get(cp))
|
.map(|i| i.name_index.get(cp))
|
||||||
.collect::<Result<Vec<_>, ParseErr>>()?
|
.collect::<Vec<_>>()
|
||||||
.join(",")
|
.join(",")
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -42,7 +39,7 @@ pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dy
|
||||||
|
|
||||||
writeln!(w, " Attributes:")?;
|
writeln!(w, " Attributes:")?;
|
||||||
for attr in &class.attributes {
|
for attr in &class.attributes {
|
||||||
writeln!(w, " {}", &attr.attribute_name_index.get(cp)?)?;
|
writeln!(w, " {}", &attr.attribute_name_index.get(cp))?;
|
||||||
}
|
}
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
|
||||||
|
|
@ -51,8 +48,8 @@ pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dy
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
" {} {}",
|
" {} {}",
|
||||||
&field.descriptor_index.get(cp)?,
|
&field.descriptor_index.get(cp),
|
||||||
&field.name_index.get(cp)?
|
&field.name_index.get(cp)
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
|
@ -62,8 +59,8 @@ pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dy
|
||||||
writeln!(
|
writeln!(
|
||||||
w,
|
w,
|
||||||
" {} {}",
|
" {} {}",
|
||||||
&method.descriptor_index.get(cp)?,
|
&method.descriptor_index.get(cp),
|
||||||
&method.name_index.get(cp)?,
|
&method.name_index.get(cp),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ mod model;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use crate::cp_info::FromCpInfo;
|
use crate::cp_info::ValidateCpInfo;
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
|
@ -46,9 +46,9 @@ impl<'a> Data<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a u2 and validates it in the constant pool
|
/// Parses a u2 and validates it in the constant pool
|
||||||
fn cp<'pool, T: FromCpInfo<'pool>>(&mut self, pool: &'pool [CpInfo]) -> Result<FromPool<T>> {
|
fn cp<T: ValidateCpInfo>(&mut self, pool: &[CpInfo]) -> Result<FromPool<T>> {
|
||||||
let index = self.u2()?;
|
let index = self.u2()?;
|
||||||
let _ = T::try_from_cp_info(pool, index)?;
|
T::validate_cp_info(pool, index)?;
|
||||||
Ok(index.into())
|
Ok(index.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,9 +117,12 @@ macro_rules! parse_primitive {
|
||||||
|
|
||||||
parse_primitive!(u1, u2, u4);
|
parse_primitive!(u1, u2, u4);
|
||||||
|
|
||||||
impl<T> Parse for FromPool<T> {
|
impl<T> Parse for FromPool<T>
|
||||||
|
where
|
||||||
|
T: ValidateCpInfo,
|
||||||
|
{
|
||||||
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(data.u2()?.into())
|
data.cp(cp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +132,9 @@ impl Parse for ClassFile {
|
||||||
assert_eq!(magic, 0xCAFEBABE);
|
assert_eq!(magic, 0xCAFEBABE);
|
||||||
let minor_version = data.u2()?;
|
let minor_version = data.u2()?;
|
||||||
let major_version = data.u2()?;
|
let major_version = data.u2()?;
|
||||||
|
dbg!("reached constant pool");
|
||||||
let constant_pool = parse_vec(data.u2()? - 1, data, cp)?; // the minus one is important
|
let constant_pool = parse_vec(data.u2()? - 1, data, cp)?; // the minus one is important
|
||||||
|
dbg!("after constant pool");
|
||||||
let cp = &constant_pool;
|
let cp = &constant_pool;
|
||||||
let access_flags = data.u2()?;
|
let access_flags = data.u2()?;
|
||||||
let this_class = data.cp(cp)?;
|
let this_class = data.cp(cp)?;
|
||||||
|
|
@ -160,6 +165,7 @@ impl Parse for ClassFile {
|
||||||
impl Parse for CpInfo {
|
impl Parse for CpInfo {
|
||||||
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
let tag = data.u1()?;
|
let tag = data.u1()?;
|
||||||
|
dbg!(tag);
|
||||||
|
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
7 => Self {
|
7 => Self {
|
||||||
|
|
@ -302,7 +308,7 @@ impl Parse for AttributeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeCodeException {
|
impl Parse for AttributeCodeException {
|
||||||
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
fn parse(data: &mut Data, _cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.last_u2()?,
|
start_pc: data.last_u2()?,
|
||||||
end_pc: data.last_u2()?,
|
end_pc: data.last_u2()?,
|
||||||
|
|
@ -357,7 +363,7 @@ impl Parse for StackMapFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for VerificationTypeInfo {
|
impl Parse for VerificationTypeInfo {
|
||||||
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
fn parse(data: &mut Data, _cp: &[CpInfo]) -> Result<Self> {
|
||||||
let tag = data.u1()?;
|
let tag = data.u1()?;
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
0 => Self::Top { tag },
|
0 => Self::Top { tag },
|
||||||
|
|
@ -397,7 +403,7 @@ impl Parse for AttributeInnerClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeLineNumber {
|
impl Parse for AttributeLineNumber {
|
||||||
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
fn parse(data: &mut Data, _cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.u2()?,
|
start_pc: data.u2()?,
|
||||||
line_number: data.u2()?,
|
line_number: data.u2()?,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::*;
|
use crate::{u1, u2, u4, CpInfo, CpInfoInner, ParseErr};
|
||||||
use crate::ParseErr;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// An index into the constant pool of the class
|
/// An index into the constant pool of the class
|
||||||
|
|
@ -18,6 +18,7 @@ pub struct FromPool<T> {
|
||||||
impl<T: Clone> Copy for FromPool<T> {}
|
impl<T: Clone> Copy for FromPool<T> {}
|
||||||
|
|
||||||
impl<T> From<u2> for FromPool<T> {
|
impl<T> From<u2> for FromPool<T> {
|
||||||
|
#[inline]
|
||||||
fn from(n: u2) -> Self {
|
fn from(n: u2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: n,
|
inner: n,
|
||||||
|
|
@ -39,7 +40,7 @@ where
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, pool: &'pool [CpInfo]) -> T::Target {
|
pub fn get(&self, pool: &'pool [CpInfo]) -> T::Target {
|
||||||
T::from_cp_info(&pool[self.inner as usize - 1])
|
T::from_cp_info_with_index(pool, self.inner)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,15 +53,56 @@ where
|
||||||
if self.inner == 0 {
|
if self.inner == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(T::from_cp_info(&pool[self.inner as usize - 1]))
|
Some(T::from_cp_info_with_index(pool, self.inner))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromCpInfo<'pool> {
|
pub trait ValidateCpInfo {
|
||||||
|
/// check that the constant pool entry has the correct type
|
||||||
|
/// `index` is the original, non-null index (it can be 0 optional constants)
|
||||||
|
fn validate_cp_info(info: &[CpInfo], index: u2) -> Result<(), ParseErr>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FromCpInfo<'pool>: ValidateCpInfo {
|
||||||
type Target;
|
type Target;
|
||||||
fn from_cp_info(info: &'pool CpInfo) -> Self::Target;
|
fn from_cp_info(info: &'pool CpInfo) -> Self::Target;
|
||||||
fn try_from_cp_info(info: &'pool [CpInfo], index: u2) -> Result<Self::Target, ParseErr>;
|
fn from_cp_info_with_index(info: &'pool [CpInfo], index: u2) -> Self::Target {
|
||||||
|
Self::from_cp_info(&info[index as usize - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'pool, T> FromCpInfo<'pool> for Option<T>
|
||||||
|
where
|
||||||
|
T: FromCpInfo<'pool>,
|
||||||
|
{
|
||||||
|
type Target = Option<T::Target>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_cp_info(_info: &'pool CpInfo) -> Self::Target {
|
||||||
|
unreachable!("FromPool<Option<T>> should always be get through `from_cp_info_with_index`")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_cp_info_with_index(info: &'pool [CpInfo], index: u2) -> Self::Target {
|
||||||
|
if index == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(T::from_cp_info_with_index(info, index))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ValidateCpInfo for Option<T>
|
||||||
|
where
|
||||||
|
T: ValidateCpInfo,
|
||||||
|
{
|
||||||
|
fn validate_cp_info(info: &[CpInfo], index: u2) -> Result<(), ParseErr> {
|
||||||
|
if index == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
T::validate_cp_info(info, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_try_from_cp {
|
macro_rules! impl_try_from_cp {
|
||||||
|
|
@ -76,14 +118,20 @@ macro_rules! impl_try_from_cp {
|
||||||
_kind => unreachable!(),
|
_kind => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
impl ValidateCpInfo for $name {
|
||||||
fn try_from_cp_info(info: &'pool [CpInfo], index: u2) -> Result<Self::Target, ParseErr> {
|
fn validate_cp_info(info: &[CpInfo], index: u2) -> Result<(), ParseErr> {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
return Err(ParseErr("Index must not be 0".to_string()));
|
return Err(ParseErr("Index must not be 0".to_string()));
|
||||||
}
|
}
|
||||||
|
// todo this here might actually be an empty constant pool depending on whether is is still parsing the constant pool
|
||||||
|
// it needs to be checked after testing
|
||||||
|
// not now
|
||||||
|
// pls
|
||||||
|
// i hate this
|
||||||
match &info[index as usize - 1].inner {
|
match &info[index as usize - 1].inner {
|
||||||
CpInfoInner::$name(class) => Ok(class),
|
CpInfoInner::$name(_) => Ok(()),
|
||||||
kind => Err(ParseErr(format!(
|
kind => Err(ParseErr(format!(
|
||||||
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
||||||
kind
|
kind
|
||||||
|
|
@ -95,40 +143,54 @@ macro_rules! impl_try_from_cp {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'pool> FromCpInfo<'pool> for CpInfoInner {
|
||||||
|
type Target = &'pool Self;
|
||||||
|
|
||||||
|
fn from_cp_info(info: &'pool CpInfo) -> Self::Target {
|
||||||
|
&info.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ValidateCpInfo for CpInfoInner {
|
||||||
|
fn validate_cp_info(_info: &[CpInfo], _index: u2) -> Result<(), ParseErr> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
pub name_index: FromPool<cp_info::Utf8>,
|
pub name_index: FromPool<Utf8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct Fieldref {
|
pub struct Fieldref {
|
||||||
/// May be a class or interface type
|
/// May be a class or interface type
|
||||||
pub class_index: FromPool<cp_info::Class>,
|
pub class_index: FromPool<Class>,
|
||||||
/// Entry must be `NameAndType`
|
/// Entry must be `NameAndType`
|
||||||
pub name_and_type_index: FromPool<cp_info::NameAndType>,
|
pub name_and_type_index: FromPool<NameAndType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct MethodRef {
|
pub struct MethodRef {
|
||||||
/// Must be a class type
|
/// Must be a class type
|
||||||
pub class_index: FromPool<cp_info::Class>,
|
pub class_index: FromPool<Class>,
|
||||||
/// Entry must be `NameAndType`
|
/// Entry must be `NameAndType`
|
||||||
pub name_and_type_index: FromPool<cp_info::NameAndType>,
|
pub name_and_type_index: FromPool<NameAndType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct InterfaceMethodref {
|
pub struct InterfaceMethodref {
|
||||||
/// Must be an interface type
|
/// Must be an interface type
|
||||||
pub class_index: FromPool<cp_info::Class>,
|
pub class_index: FromPool<Class>,
|
||||||
/// Entry must be `NameAndType`
|
/// Entry must be `NameAndType`
|
||||||
pub name_and_type_index: FromPool<cp_info::NameAndType>,
|
pub name_and_type_index: FromPool<NameAndType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct String {
|
pub struct String {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
pub string_index: FromPool<cp_info::Utf8>,
|
pub string_index: FromPool<Utf8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
|
@ -165,9 +227,9 @@ pub struct Double {
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct NameAndType {
|
pub struct NameAndType {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
pub name_index: FromPool<cp_info::Utf8>,
|
pub name_index: FromPool<Utf8>,
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
pub descriptor_index: FromPool<cp_info::Utf8>,
|
pub descriptor_index: FromPool<Utf8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
|
|
@ -187,15 +249,15 @@ pub struct MethodHandle {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum MethodHandleIndex {
|
pub enum MethodHandleIndex {
|
||||||
Field(FromPool<cp_info::Fieldref>),
|
Field(FromPool<Fieldref>),
|
||||||
Method(FromPool<cp_info::MethodInfo>),
|
Method(FromPool<MethodRef>),
|
||||||
Interface(FromPool<cp_info::InterfaceMethodref>),
|
Interface(FromPool<InterfaceMethodref>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
pub struct MethodType {
|
pub struct MethodType {
|
||||||
/// Entry must be `Utf8`
|
/// Entry must be `Utf8`
|
||||||
pub descriptor_index: FromPool<cp_info::Utf8>,
|
pub descriptor_index: FromPool<Utf8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||||
|
|
@ -203,7 +265,7 @@ pub struct InvokeDynamic {
|
||||||
/// Must be a valid index into the `bootstrap_methods` array of the bootstrap method table of this class field
|
/// Must be a valid index into the `bootstrap_methods` array of the bootstrap method table of this class field
|
||||||
pub bootstrap_method_attr_index: u2,
|
pub bootstrap_method_attr_index: u2,
|
||||||
/// Entry must `NameAndType`
|
/// Entry must `NameAndType`
|
||||||
pub name_and_type_index: FromPool<cp_info::NameAndType>,
|
pub name_and_type_index: FromPool<NameAndType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// default implementations
|
// default implementations
|
||||||
|
|
@ -224,6 +286,21 @@ impl_try_from_cp!(
|
||||||
InvokeDynamic
|
InvokeDynamic
|
||||||
);
|
);
|
||||||
|
|
||||||
|
impl ValidateCpInfo for Utf8 {
|
||||||
|
fn validate_cp_info(info: &[CpInfo], index: u2) -> Result<(), ParseErr> {
|
||||||
|
if index == 0 {
|
||||||
|
return Err(ParseErr("Index must not be 0".to_string()));
|
||||||
|
}
|
||||||
|
match &info[index as usize - 1].inner {
|
||||||
|
CpInfoInner::Utf8(_) => Ok(()),
|
||||||
|
kind => Err(ParseErr(format!(
|
||||||
|
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
||||||
|
kind
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// custom implementations
|
// custom implementations
|
||||||
impl<'pool> FromCpInfo<'pool> for Utf8 {
|
impl<'pool> FromCpInfo<'pool> for Utf8 {
|
||||||
type Target = &'pool str;
|
type Target = &'pool str;
|
||||||
|
|
@ -235,18 +312,4 @@ impl<'pool> FromCpInfo<'pool> for Utf8 {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from_cp_info(info: &'pool [CpInfo], index: u2) -> Result<Self::Target, ParseErr> {
|
|
||||||
if index == 0 {
|
|
||||||
return Err(ParseErr("Index must not be 0".to_string()));
|
|
||||||
}
|
|
||||||
match &info[index as usize - 1].inner {
|
|
||||||
CpInfoInner::Utf8(class) => Ok(&class.bytes),
|
|
||||||
kind => Err(ParseErr(format!(
|
|
||||||
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
|
||||||
kind
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
//! [The .class specs](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html)
|
//! [The .class specs](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html)
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
/// All of the Constants in the Constant Pool
|
/// All of the Constants in the Constant Pool
|
||||||
pub mod cp_info;
|
pub mod cp_info;
|
||||||
|
|
||||||
|
|
@ -118,15 +116,6 @@ pub struct AttributeInfo {
|
||||||
pub inner: AttributeInfoInner,
|
pub inner: AttributeInfoInner,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
|
||||||
pub enum ConstantValueIndex {
|
|
||||||
Long(cp_info::Long),
|
|
||||||
Float(cp_info::Float),
|
|
||||||
Double(cp_info::Double),
|
|
||||||
Integer(cp_info::Integer),
|
|
||||||
String(cp_info::String),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The Attributes, without the two common fields
|
/// The Attributes, without the two common fields
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum AttributeInfoInner {
|
pub enum AttributeInfoInner {
|
||||||
|
|
@ -138,7 +127,7 @@ pub enum AttributeInfoInner {
|
||||||
/// Only on fields, the constant value of that field
|
/// Only on fields, the constant value of that field
|
||||||
ConstantValue {
|
ConstantValue {
|
||||||
/// Must be of type `Long`/`Float`/`Double`/`Integer`/`String`
|
/// Must be of type `Long`/`Float`/`Double`/`Integer`/`String`
|
||||||
constantvalue_index: FromPool<ConstantValueIndex>,
|
constantvalue_index: FromPool<CpInfoInner>,
|
||||||
},
|
},
|
||||||
/// Only on methods, contains JVM instructions and auxiliary information for a single method
|
/// Only on methods, contains JVM instructions and auxiliary information for a single method
|
||||||
Code {
|
Code {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue