mirror of
https://github.com/Noratrieb/coldsquare.git
synced 2026-01-14 16:35:10 +01:00
Actually good handling of the Constant Pool indecies
The code does not compile yet, because `FromCpInfo<'_>` needs to be implemented for some more types.
This commit is contained in:
parent
5ec9260b59
commit
2a85d1fdfd
4 changed files with 188 additions and 153 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use file_parser::{ClassFile, ParseErr};
|
use file_parser::ClassFile;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
|
@ -16,7 +16,11 @@ pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dy
|
||||||
writeln!(
|
writeln!(
|
||||||
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.maybe_get(cp) {
|
||||||
|
None => "<none>",
|
||||||
|
Some(class) => &class.name_index.get(cp),
|
||||||
|
},
|
||||||
if class.interfaces.len() == 0 {
|
if class.interfaces.len() == 0 {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -27,22 +31,16 @@ pub fn display_class<W: Write>(mut w: W, class: &ClassFile) -> Result<(), Box<dy
|
||||||
.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(",")
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
match class.super_class.get(cp)? {
|
|
||||||
None => "<none>",
|
|
||||||
Some(class) => &class.name_index.get(cp)?,
|
|
||||||
}
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
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 +49,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 +60,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,6 +2,7 @@ mod model;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
|
use crate::cp_info::FromCpInfo;
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
|
@ -26,7 +27,7 @@ struct Data<'a> {
|
||||||
|
|
||||||
pub fn parse_class_file(data: &[u1]) -> Result<ClassFile> {
|
pub fn parse_class_file(data: &[u1]) -> Result<ClassFile> {
|
||||||
let mut data = Data::new(data);
|
let mut data = Data::new(data);
|
||||||
ClassFile::parse(&mut data)
|
ClassFile::parse(&mut data, &[])
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Data<'a> {
|
impl<'a> Data<'a> {
|
||||||
|
|
@ -44,8 +45,11 @@ impl<'a> Data<'a> {
|
||||||
Ok(((self.u1()? as u2) << 8) | self.u1()? as u2)
|
Ok(((self.u1()? as u2) << 8) | self.u1()? as u2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cp<T>(&mut self) -> Result<FromPool<T>> {
|
/// Parses a u2 and validates it in the constant pool
|
||||||
Ok(self.u2()?.into())
|
fn cp<'pool, T: FromCpInfo<'pool>>(&mut self, pool: &'pool [CpInfo]) -> Result<FromPool<T>> {
|
||||||
|
let index = self.u2()?;
|
||||||
|
let _ = T::try_from_cp_info(pool, index)?;
|
||||||
|
Ok(index.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u4(&mut self) -> Result<u4> {
|
fn u4(&mut self) -> Result<u4> {
|
||||||
|
|
@ -84,16 +88,16 @@ impl<'a> Data<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Parse {
|
trait Parse {
|
||||||
fn parse(data: &mut Data) -> Result<Self>
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_vec<T: Parse, S: Into<usize>>(len: S, data: &mut Data) -> Result<Vec<T>> {
|
fn parse_vec<T: Parse, S: Into<usize>>(len: S, data: &mut Data, cp: &[CpInfo]) -> Result<Vec<T>> {
|
||||||
let len = len.into();
|
let len = len.into();
|
||||||
let mut vec = Vec::with_capacity(len);
|
let mut vec = Vec::with_capacity(len);
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
vec.push(T::parse(data)?);
|
vec.push(T::parse(data, cp)?);
|
||||||
}
|
}
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +105,7 @@ fn parse_vec<T: Parse, S: Into<usize>>(len: S, data: &mut Data) -> Result<Vec<T>
|
||||||
macro_rules! parse_primitive {
|
macro_rules! parse_primitive {
|
||||||
($($value:ident),*) => {
|
($($value:ident),*) => {
|
||||||
$(impl Parse for $value {
|
$(impl Parse for $value {
|
||||||
fn parse(data: &mut Data) -> Result<Self>
|
fn parse(data: &mut Data, _cp: &[CpInfo]) -> Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
|
@ -114,25 +118,26 @@ 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> {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(data.u2()?.into())
|
Ok(data.u2()?.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ClassFile {
|
impl Parse for ClassFile {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
let magic = data.u4()?;
|
let magic = data.u4()?;
|
||||||
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()?;
|
||||||
let constant_pool = parse_vec(data.u2()? - 1, data)?; // the minus one is important
|
let constant_pool = parse_vec(data.u2()? - 1, data, cp)?; // the minus one is important
|
||||||
|
let cp = &constant_pool;
|
||||||
let access_flags = data.u2()?;
|
let access_flags = data.u2()?;
|
||||||
let this_class = data.cp()?;
|
let this_class = data.cp(cp)?;
|
||||||
let super_class = data.cp()?;
|
let super_class = data.cp(cp)?;
|
||||||
let interfaces = parse_vec(data.u2()?, data)?;
|
let interfaces = parse_vec(data.u2()?, data, cp)?;
|
||||||
let fields = parse_vec(data.u2()?, data)?;
|
let fields = parse_vec(data.u2()?, data, cp)?;
|
||||||
let methods = parse_vec(data.u2()?, data)?;
|
let methods = parse_vec(data.u2()?, data, cp)?;
|
||||||
let attributes = parse_vec(data.u2()?, data)?;
|
let attributes = parse_vec(data.u2()?, data, cp)?;
|
||||||
|
|
||||||
let mut class = Self {
|
let mut class = Self {
|
||||||
magic,
|
magic,
|
||||||
|
|
@ -153,41 +158,41 @@ impl Parse for ClassFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for CpInfo {
|
impl Parse for CpInfo {
|
||||||
fn parse(data: &mut Data) -> 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 {
|
||||||
7 => Self {
|
7 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::Class(cp_info::Class {
|
inner: CpInfoInner::Class(cp_info::Class {
|
||||||
name_index: data.cp()?,
|
name_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
9 => Self {
|
9 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::Fieldref(cp_info::Fieldref {
|
inner: CpInfoInner::Fieldref(cp_info::Fieldref {
|
||||||
class_index: data.cp()?,
|
class_index: data.cp(cp)?,
|
||||||
name_and_type_index: data.cp()?,
|
name_and_type_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
10 => Self {
|
10 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::MethodRef(cp_info::MethodRef {
|
inner: CpInfoInner::MethodRef(cp_info::MethodRef {
|
||||||
class_index: data.cp()?,
|
class_index: data.cp(cp)?,
|
||||||
name_and_type_index: data.cp()?,
|
name_and_type_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
11 => Self {
|
11 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::InterfaceMethodref(cp_info::InterfaceMethodref {
|
inner: CpInfoInner::InterfaceMethodref(cp_info::InterfaceMethodref {
|
||||||
class_index: data.cp()?,
|
class_index: data.cp(cp)?,
|
||||||
name_and_type_index: data.cp()?,
|
name_and_type_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
8 => Self {
|
8 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::String(cp_info::String {
|
inner: CpInfoInner::String(cp_info::String {
|
||||||
string_index: data.cp()?,
|
string_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
3 => Self {
|
3 => Self {
|
||||||
|
|
@ -215,14 +220,14 @@ impl Parse for CpInfo {
|
||||||
12 => Self {
|
12 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::NameAndType(cp_info::NameAndType {
|
inner: CpInfoInner::NameAndType(cp_info::NameAndType {
|
||||||
name_index: data.cp()?,
|
name_index: data.cp(cp)?,
|
||||||
descriptor_index: data.cp()?,
|
descriptor_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
1 => Self {
|
1 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
inner: CpInfoInner::Utf8(cp_info::Utf8 {
|
||||||
bytes: String::from_utf8(parse_vec(data.u2()?, data)?).map_err(|err| {
|
bytes: String::from_utf8(parse_vec(data.u2()?, data, cp)?).map_err(|err| {
|
||||||
ParseErr(format!("Invalid utf8 in CpInfo::Utf8: {}", err))
|
ParseErr(format!("Invalid utf8 in CpInfo::Utf8: {}", err))
|
||||||
})?,
|
})?,
|
||||||
}),
|
}),
|
||||||
|
|
@ -232,9 +237,9 @@ impl Parse for CpInfo {
|
||||||
inner: CpInfoInner::MethodHandle(cp_info::MethodHandle {
|
inner: CpInfoInner::MethodHandle(cp_info::MethodHandle {
|
||||||
reference_kind: data.u1()?,
|
reference_kind: data.u1()?,
|
||||||
reference_index: match data.last_u1()? {
|
reference_index: match data.last_u1()? {
|
||||||
1..=4 => cp_info::MethodHandleIndex::Field(data.cp()?),
|
1..=4 => cp_info::MethodHandleIndex::Field(data.cp(cp)?),
|
||||||
5..=8 => cp_info::MethodHandleIndex::Method(data.cp()?),
|
5..=8 => cp_info::MethodHandleIndex::Method(data.cp(cp)?),
|
||||||
9 => cp_info::MethodHandleIndex::Interface(data.cp()?),
|
9 => cp_info::MethodHandleIndex::Interface(data.cp(cp)?),
|
||||||
n => {
|
n => {
|
||||||
return Err(ParseErr(format!(
|
return Err(ParseErr(format!(
|
||||||
"Invalid MethodHandle reference kind: {}",
|
"Invalid MethodHandle reference kind: {}",
|
||||||
|
|
@ -247,14 +252,14 @@ impl Parse for CpInfo {
|
||||||
16 => Self {
|
16 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::MethodType(cp_info::MethodType {
|
inner: CpInfoInner::MethodType(cp_info::MethodType {
|
||||||
descriptor_index: data.cp()?,
|
descriptor_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
18 => Self {
|
18 => Self {
|
||||||
tag,
|
tag,
|
||||||
inner: CpInfoInner::InvokeDynamic(cp_info::InvokeDynamic {
|
inner: CpInfoInner::InvokeDynamic(cp_info::InvokeDynamic {
|
||||||
bootstrap_method_attr_index: data.u2()?,
|
bootstrap_method_attr_index: data.u2()?,
|
||||||
name_and_type_index: data.cp()?,
|
name_and_type_index: data.cp(cp)?,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
_ => Err(ParseErr(format!("Invalid CPInfo tag: {}", tag)))?,
|
_ => Err(ParseErr(format!("Invalid CPInfo tag: {}", tag)))?,
|
||||||
|
|
@ -263,41 +268,41 @@ impl Parse for CpInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for FieldInfo {
|
impl Parse for FieldInfo {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
access_flags: data.u2()?,
|
access_flags: data.u2()?,
|
||||||
name_index: data.cp()?,
|
name_index: data.cp(cp)?,
|
||||||
descriptor_index: data.cp()?,
|
descriptor_index: data.cp(cp)?,
|
||||||
attributes: parse_vec(data.u2()?, data)?,
|
attributes: parse_vec(data.u2()?, data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for MethodInfo {
|
impl Parse for MethodInfo {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
access_flags: data.u2()?,
|
access_flags: data.u2()?,
|
||||||
name_index: data.cp()?,
|
name_index: data.cp(cp)?,
|
||||||
descriptor_index: data.cp()?,
|
descriptor_index: data.cp(cp)?,
|
||||||
attributes: parse_vec(data.u2()?, data)?,
|
attributes: parse_vec(data.u2()?, data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeInfo {
|
impl Parse for AttributeInfo {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
attribute_name_index: data.cp()?,
|
attribute_name_index: data.cp(cp)?,
|
||||||
attribute_length: data.u4()?,
|
attribute_length: data.u4()?,
|
||||||
inner: AttributeInfoInner::Unknown {
|
inner: AttributeInfoInner::Unknown {
|
||||||
attribute_content: parse_vec(data.last_u4()? as usize, data)?,
|
attribute_content: parse_vec(data.last_u4()? as usize, data, cp)?,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeCodeException {
|
impl Parse for AttributeCodeException {
|
||||||
fn parse(data: &mut Data) -> 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()?,
|
||||||
|
|
@ -308,19 +313,19 @@ impl Parse for AttributeCodeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for StackMapFrame {
|
impl Parse for StackMapFrame {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
let frame_type = data.u1()?;
|
let frame_type = data.u1()?;
|
||||||
|
|
||||||
Ok(match frame_type {
|
Ok(match frame_type {
|
||||||
0..=63 => Self::SameFrame { frame_type },
|
0..=63 => Self::SameFrame { frame_type },
|
||||||
64..=127 => Self::SameLocals1StackItemFrame {
|
64..=127 => Self::SameLocals1StackItemFrame {
|
||||||
frame_type,
|
frame_type,
|
||||||
stack: VerificationTypeInfo::parse(data)?,
|
stack: VerificationTypeInfo::parse(data, cp)?,
|
||||||
},
|
},
|
||||||
247 => Self::SameLocals1StackItemFrameExtended {
|
247 => Self::SameLocals1StackItemFrameExtended {
|
||||||
frame_type,
|
frame_type,
|
||||||
offset_delta: data.u2()?,
|
offset_delta: data.u2()?,
|
||||||
stack: VerificationTypeInfo::parse(data)?,
|
stack: VerificationTypeInfo::parse(data, cp)?,
|
||||||
},
|
},
|
||||||
246..=250 => Self::ChopFrame {
|
246..=250 => Self::ChopFrame {
|
||||||
frame_type,
|
frame_type,
|
||||||
|
|
@ -333,13 +338,13 @@ impl Parse for StackMapFrame {
|
||||||
252..=254 => Self::AppendFrame {
|
252..=254 => Self::AppendFrame {
|
||||||
frame_type,
|
frame_type,
|
||||||
offset_delta: data.u2()?,
|
offset_delta: data.u2()?,
|
||||||
locals: parse_vec(data.last_u2()?, data)?,
|
locals: parse_vec(data.last_u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
255 => Self::FullFrame {
|
255 => Self::FullFrame {
|
||||||
frame_type,
|
frame_type,
|
||||||
offset_delta: data.u2()?,
|
offset_delta: data.u2()?,
|
||||||
locals: parse_vec(data.u2()?, data)?,
|
locals: parse_vec(data.u2()?, data, cp)?,
|
||||||
stack: parse_vec(data.u2()?, data)?,
|
stack: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
_ => Err(ParseErr(format!(
|
_ => Err(ParseErr(format!(
|
||||||
"Invalid StackMapFrame type: {}",
|
"Invalid StackMapFrame type: {}",
|
||||||
|
|
@ -350,7 +355,7 @@ impl Parse for StackMapFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for VerificationTypeInfo {
|
impl Parse for VerificationTypeInfo {
|
||||||
fn parse(data: &mut Data) -> 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 },
|
||||||
|
|
@ -377,18 +382,18 @@ impl Parse for VerificationTypeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeInnerClass {
|
impl Parse for AttributeInnerClass {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner_class_info_index: data.cp()?,
|
inner_class_info_index: data.cp(cp)?,
|
||||||
outer_class_info_index: data.cp()?,
|
outer_class_info_index: data.cp(cp)?,
|
||||||
inner_class_name_index: data.cp()?,
|
inner_class_name_index: data.cp(cp)?,
|
||||||
inner_class_access_flags: data.u2()?,
|
inner_class_access_flags: data.u2()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeLineNumber {
|
impl Parse for AttributeLineNumber {
|
||||||
fn parse(data: &mut Data) -> 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()?,
|
||||||
|
|
@ -397,62 +402,64 @@ impl Parse for AttributeLineNumber {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AttributeLocalVariableTable {
|
impl Parse for AttributeLocalVariableTable {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
start_pc: data.u2()?,
|
start_pc: data.u2()?,
|
||||||
length: data.u2()?,
|
length: data.u2()?,
|
||||||
name_index: data.cp()?,
|
name_index: data.cp(cp)?,
|
||||||
descriptor_or_signature_index: data.cp()?,
|
descriptor_or_signature_index: data.cp(cp)?,
|
||||||
index: data.u2()?,
|
index: data.u2()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Annotation {
|
impl Parse for Annotation {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
type_index: data.cp()?,
|
type_index: data.cp(cp)?,
|
||||||
num_element_value_pairs: data.u2()?,
|
num_element_value_pairs: data.u2()?,
|
||||||
element_value_pairs: parse_vec(data.last_u2()?, data)?,
|
element_value_pairs: parse_vec(data.last_u2()?, data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AnnotationElementValuePair {
|
impl Parse for AnnotationElementValuePair {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
element_name_index: data.cp()?,
|
element_name_index: data.cp(cp)?,
|
||||||
element_name_name: AnnotationElementValue::parse(data)?,
|
element_name_name: AnnotationElementValue::parse(data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AnnotationElementValue {
|
impl Parse for AnnotationElementValue {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
tag: data.u1()?,
|
tag: data.u1()?,
|
||||||
value: AnnotationElementValueValue::parse(data)?,
|
value: AnnotationElementValueValue::parse(data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AnnotationElementValueValue {
|
impl Parse for AnnotationElementValueValue {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
let tag = data.last_u1()? as char;
|
let tag = data.last_u1()? as char;
|
||||||
Ok(match tag {
|
Ok(match tag {
|
||||||
'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' => {
|
'B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's' => Self::ConstValueIndex {
|
||||||
Self::ConstValueIndex { index: data.cp()? }
|
index: data.u2()?.into(),
|
||||||
}
|
},
|
||||||
'e' => Self::EnumConstValue {
|
'e' => Self::EnumConstValue {
|
||||||
type_name_index: data.cp()?,
|
type_name_index: data.cp(cp)?,
|
||||||
const_name_index: data.cp()?,
|
const_name_index: data.cp(cp)?,
|
||||||
|
},
|
||||||
|
'c' => Self::ClassInfoIndex {
|
||||||
|
index: data.cp(cp)?,
|
||||||
},
|
},
|
||||||
'c' => Self::ClassInfoIndex { index: data.cp()? },
|
|
||||||
'@' => Self::AnnotationValue {
|
'@' => Self::AnnotationValue {
|
||||||
annotation: Box::new(Annotation::parse(data)?),
|
annotation: Box::new(Annotation::parse(data, cp)?),
|
||||||
},
|
},
|
||||||
'[' => Self::ArrayValue {
|
'[' => Self::ArrayValue {
|
||||||
values: parse_vec(data.u2()?, data)?,
|
values: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
_ => Err(ParseErr(format!(
|
_ => Err(ParseErr(format!(
|
||||||
"Invalid AnnotationElementValueValue tag: {}",
|
"Invalid AnnotationElementValueValue tag: {}",
|
||||||
|
|
@ -463,18 +470,18 @@ impl Parse for AnnotationElementValueValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ParameterAnnotation {
|
impl Parse for ParameterAnnotation {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
annotations: parse_vec(data.u2()?, data)?,
|
annotations: parse_vec(data.u2()?, data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BootstrapMethod {
|
impl Parse for BootstrapMethod {
|
||||||
fn parse(data: &mut Data) -> Result<Self> {
|
fn parse(data: &mut Data, cp: &[CpInfo]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
bootstrap_method_ref: data.cp()?,
|
bootstrap_method_ref: data.cp(cp)?,
|
||||||
bootstrap_arguments: parse_vec(data.u2()?, data)?,
|
bootstrap_arguments: parse_vec(data.u2()?, data, cp)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -535,7 +542,7 @@ impl AttributeInfo {
|
||||||
} => (attribute_name_index, attribute_length, attribute_content),
|
} => (attribute_name_index, attribute_length, attribute_content),
|
||||||
_ => unreachable!("Attribute already resolved"),
|
_ => unreachable!("Attribute already resolved"),
|
||||||
};
|
};
|
||||||
let info = match pool.get((*index) as usize - 1) {
|
let info = match pool.get((index.inner()) as usize - 1) {
|
||||||
Some(CpInfo {
|
Some(CpInfo {
|
||||||
inner: CpInfoInner::Utf8(cp_info::Utf8 { bytes, .. }),
|
inner: CpInfoInner::Utf8(cp_info::Utf8 { bytes, .. }),
|
||||||
..
|
..
|
||||||
|
|
@ -554,7 +561,7 @@ impl AttributeInfo {
|
||||||
attribute_length: u32,
|
attribute_length: u32,
|
||||||
name: &str,
|
name: &str,
|
||||||
data: &mut Data,
|
data: &mut Data,
|
||||||
pool: &[CpInfo],
|
cp: &[CpInfo],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let _ = std::mem::replace(
|
let _ = std::mem::replace(
|
||||||
self,
|
self,
|
||||||
|
|
@ -563,7 +570,7 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::ConstantValue {
|
inner: AttributeInfoInner::ConstantValue {
|
||||||
constantvalue_index: data.cp()?,
|
constantvalue_index: data.cp(cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Code" => {
|
"Code" => {
|
||||||
|
|
@ -573,9 +580,9 @@ impl AttributeInfo {
|
||||||
inner: AttributeInfoInner::Code {
|
inner: AttributeInfoInner::Code {
|
||||||
max_stack: data.u2()?,
|
max_stack: data.u2()?,
|
||||||
max_locals: data.u2()?,
|
max_locals: data.u2()?,
|
||||||
code: parse_vec(data.u4()? as usize, data)?,
|
code: parse_vec(data.u4()? as usize, data, cp)?,
|
||||||
exception_table: parse_vec(data.u2()?, data)?,
|
exception_table: parse_vec(data.u2()?, data, cp)?,
|
||||||
attributes: parse_vec(data.u2()?, data)?,
|
attributes: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
if let AttributeInfoInner::Code {
|
if let AttributeInfoInner::Code {
|
||||||
|
|
@ -584,7 +591,7 @@ impl AttributeInfo {
|
||||||
{
|
{
|
||||||
attributes
|
attributes
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|attr| attr.resolve_attribute(pool))
|
.map(|attr| attr.resolve_attribute(cp))
|
||||||
.collect::<Result<Vec<()>>>()?;
|
.collect::<Result<Vec<()>>>()?;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
@ -596,29 +603,29 @@ impl AttributeInfo {
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::StackMapTable {
|
inner: AttributeInfoInner::StackMapTable {
|
||||||
number_of_entries: data.u2()?,
|
number_of_entries: data.u2()?,
|
||||||
entries: parse_vec(data.last_u2()?, data)?,
|
entries: parse_vec(data.last_u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Exceptions" => Self {
|
"Exceptions" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::Exceptions {
|
inner: AttributeInfoInner::Exceptions {
|
||||||
exception_index_table: parse_vec(data.u2()?, data)?,
|
exception_index_table: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"InnerClasses" => Self {
|
"InnerClasses" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::InnerClasses {
|
inner: AttributeInfoInner::InnerClasses {
|
||||||
classes: parse_vec(data.u2()?, data)?,
|
classes: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"EnclosingMethod" => Self {
|
"EnclosingMethod" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::EnclosingMethod {
|
inner: AttributeInfoInner::EnclosingMethod {
|
||||||
class_index: data.cp()?,
|
class_index: data.cp(cp)?,
|
||||||
method_index: data.cp()?,
|
method_index: data.cp(cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Synthetic" => Self {
|
"Synthetic" => Self {
|
||||||
|
|
@ -630,42 +637,42 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::Signature {
|
inner: AttributeInfoInner::Signature {
|
||||||
signature_index: data.cp()?,
|
signature_index: data.cp(cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"SourceFile" => Self {
|
"SourceFile" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::SourceFile {
|
inner: AttributeInfoInner::SourceFile {
|
||||||
sourcefile_index: data.cp()?,
|
sourcefile_index: data.cp(cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"SourceDebugExtension" => Self {
|
"SourceDebugExtension" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::SourceDebugExtension {
|
inner: AttributeInfoInner::SourceDebugExtension {
|
||||||
debug_extension: parse_vec(data.last_u2()?, data)?,
|
debug_extension: parse_vec(data.last_u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"LineNumberTable" => Self {
|
"LineNumberTable" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::LineNumberTable {
|
inner: AttributeInfoInner::LineNumberTable {
|
||||||
line_number_table: parse_vec(data.u2()?, data)?,
|
line_number_table: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"LocalVariableTable" => Self {
|
"LocalVariableTable" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::LocalVariableTable {
|
inner: AttributeInfoInner::LocalVariableTable {
|
||||||
local_variable_table: parse_vec(data.u2()?, data)?,
|
local_variable_table: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"LocalVariableTypeTable" => Self {
|
"LocalVariableTypeTable" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::LocalVariableTypeTable {
|
inner: AttributeInfoInner::LocalVariableTypeTable {
|
||||||
local_variable_table: parse_vec(data.u2()?, data)?,
|
local_variable_table: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"Deprecated" => Self {
|
"Deprecated" => Self {
|
||||||
|
|
@ -677,28 +684,28 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::RuntimeVisibleAnnotations {
|
inner: AttributeInfoInner::RuntimeVisibleAnnotations {
|
||||||
annotations: parse_vec(data.u2()?, data)?,
|
annotations: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"RuntimeInvisibleAnnotations" => Self {
|
"RuntimeInvisibleAnnotations" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::RuntimeInvisibleAnnotations {
|
inner: AttributeInfoInner::RuntimeInvisibleAnnotations {
|
||||||
annotations: parse_vec(data.u2()?, data)?,
|
annotations: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"RuntimeVisibleParameterAnnotations" => Self {
|
"RuntimeVisibleParameterAnnotations" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::RuntimeVisibleParameterAnnotations {
|
inner: AttributeInfoInner::RuntimeVisibleParameterAnnotations {
|
||||||
parameter_annotations: parse_vec(data.u1()?, data)?,
|
parameter_annotations: parse_vec(data.u1()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"RuntimeInvisibleParameterAnnotations" => Self {
|
"RuntimeInvisibleParameterAnnotations" => Self {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::RuntimeInvisibleParameterAnnotations {
|
inner: AttributeInfoInner::RuntimeInvisibleParameterAnnotations {
|
||||||
parameter_annotations: parse_vec(data.u1()?, data)?,
|
parameter_annotations: parse_vec(data.u1()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"AnnotationDefault" => Self {
|
"AnnotationDefault" => Self {
|
||||||
|
|
@ -707,7 +714,7 @@ impl AttributeInfo {
|
||||||
inner: AttributeInfoInner::AnnotationDefault {
|
inner: AttributeInfoInner::AnnotationDefault {
|
||||||
default_value: AnnotationElementValue {
|
default_value: AnnotationElementValue {
|
||||||
tag: data.u1()?,
|
tag: data.u1()?,
|
||||||
value: AnnotationElementValueValue::parse(data)?,
|
value: AnnotationElementValueValue::parse(data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -715,7 +722,7 @@ impl AttributeInfo {
|
||||||
attribute_name_index,
|
attribute_name_index,
|
||||||
attribute_length,
|
attribute_length,
|
||||||
inner: AttributeInfoInner::BootstrapMethods {
|
inner: AttributeInfoInner::BootstrapMethods {
|
||||||
bootstrap_methods: parse_vec(data.u2()?, data)?,
|
bootstrap_methods: parse_vec(data.u2()?, data, cp)?,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
name => return Err(ParseErr(format!("Invalid Attribute name: {}", name))),
|
name => return Err(ParseErr(format!("Invalid Attribute name: {}", name))),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::ParseErr;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// An index into the constant pool of the class
|
/// An index into the constant pool of the class
|
||||||
/// `T` -> What type the target value is supposed to be. Create an enum if multiple values can be there
|
/// `T` -> What type the target value is supposed to be. Create an enum if multiple values can be there
|
||||||
|
///
|
||||||
|
/// The value this is pointing at must *always* be a entry of the correct type T
|
||||||
|
/// Type checking is done at parse time, so that the value can be get with minimal overhead
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub struct FromPool<T> {
|
pub struct FromPool<T> {
|
||||||
|
|
@ -13,14 +17,6 @@ pub struct FromPool<T> {
|
||||||
// could probably be derived if I chose a better marker
|
// could probably be derived if I chose a better marker
|
||||||
impl<T: Clone> Copy for FromPool<T> {}
|
impl<T: Clone> Copy for FromPool<T> {}
|
||||||
|
|
||||||
impl<T> std::ops::Deref for FromPool<T> {
|
|
||||||
type Target = u2;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<u2> for FromPool<T> {
|
impl<T> From<u2> for FromPool<T> {
|
||||||
fn from(n: u2) -> Self {
|
fn from(n: u2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -30,40 +26,63 @@ impl<T> From<u2> for FromPool<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromCpInfo<'a> {
|
impl<T> FromPool<T> {
|
||||||
type Target;
|
#[inline]
|
||||||
fn from_cp_info(info: &'a CpInfo) -> Result<Self::Target, ParseErr>;
|
pub const fn inner(&self) -> u2 {
|
||||||
}
|
self.inner
|
||||||
|
|
||||||
impl<'a, T> FromCpInfo<'a> for Option<T>
|
|
||||||
where
|
|
||||||
T: FromCpInfo<'a, Target = &'a T>,
|
|
||||||
T: 'a,
|
|
||||||
{
|
|
||||||
type Target = Option<&'a T>;
|
|
||||||
|
|
||||||
fn from_cp_info(info: &'a CpInfo) -> Result<Self::Target, ParseErr> {
|
|
||||||
Ok(T::from_cp_info(info).ok())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> FromPool<T>
|
impl<'pool, T> FromPool<T>
|
||||||
where
|
where
|
||||||
T: FromCpInfo<'a>,
|
T: FromCpInfo<'pool>,
|
||||||
{
|
{
|
||||||
pub fn get(&self, pool: &'a [CpInfo]) -> Result<T::Target, ParseErr> {
|
#[inline]
|
||||||
|
pub fn get(&self, pool: &'pool [CpInfo]) -> T::Target {
|
||||||
T::from_cp_info(&pool[self.inner as usize - 1])
|
T::from_cp_info(&pool[self.inner as usize - 1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'pool, T> FromPool<Option<T>>
|
||||||
|
where
|
||||||
|
T: FromCpInfo<'pool>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
pub fn maybe_get(&self, pool: &'pool [CpInfo]) -> Option<T::Target> {
|
||||||
|
if self.inner == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(T::from_cp_info(&pool[self.inner as usize - 1]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FromCpInfo<'pool> {
|
||||||
|
type Target;
|
||||||
|
fn from_cp_info(info: &'pool CpInfo) -> Self::Target;
|
||||||
|
fn try_from_cp_info(info: &'pool [CpInfo], index: u2) -> Result<Self::Target, ParseErr>;
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_try_from_cp {
|
macro_rules! impl_try_from_cp {
|
||||||
($($name:ident),*) => {
|
($($name:ident),*) => {
|
||||||
$(
|
$(
|
||||||
impl<'a> FromCpInfo<'a> for $name {
|
impl<'pool> FromCpInfo<'pool> for $name {
|
||||||
type Target = &'a Self;
|
type Target = &'pool Self;
|
||||||
|
|
||||||
fn from_cp_info(info: &'a CpInfo) -> Result<Self::Target, ParseErr> {
|
#[inline]
|
||||||
|
fn from_cp_info(info: &'pool CpInfo) -> Self::Target {
|
||||||
match &info.inner {
|
match &info.inner {
|
||||||
|
CpInfoInner::$name(class) => class,
|
||||||
|
_kind => 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::$name(class) => Ok(class),
|
CpInfoInner::$name(class) => Ok(class),
|
||||||
kind => Err(ParseErr(format!(
|
kind => Err(ParseErr(format!(
|
||||||
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
||||||
|
|
@ -206,11 +225,23 @@ impl_try_from_cp!(
|
||||||
);
|
);
|
||||||
|
|
||||||
// custom implementations
|
// custom implementations
|
||||||
impl<'a> FromCpInfo<'a> for Utf8 {
|
impl<'pool> FromCpInfo<'pool> for Utf8 {
|
||||||
type Target = &'a str;
|
type Target = &'pool str;
|
||||||
|
|
||||||
fn from_cp_info(info: &'a CpInfo) -> Result<Self::Target, ParseErr> {
|
#[inline]
|
||||||
|
fn from_cp_info(info: &'pool CpInfo) -> Self::Target {
|
||||||
match &info.inner {
|
match &info.inner {
|
||||||
|
CpInfoInner::Utf8(class) => &class.bytes,
|
||||||
|
_ => 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),
|
CpInfoInner::Utf8(class) => Ok(&class.bytes),
|
||||||
kind => Err(ParseErr(format!(
|
kind => Err(ParseErr(format!(
|
||||||
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
concat!("Expected '", stringify!($name), "', found '{:?}'"),
|
||||||
|
|
|
||||||
|
|
@ -4,7 +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 crate::ParseErr;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// All of the Constants in the Constant Pool
|
/// All of the Constants in the Constant Pool
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue