use super::*;
use std::convert::*;
pub(crate) fn read_pool_visitor(read: &mut impl Read, visitor: &mut impl Visitor) -> io::Result<()> {
let count = read_u2(read)?;
visitor.on_unused(0, UnusedPlaceholder {});
let mut index = 1; while index < count {
let tag = Type::from(read_u1(read)?);
match tag {
Class::TAG => visitor.on_class(index, Class::read_after_tag(read)?),
Fieldref::TAG => visitor.on_field(index, Fieldref::read_after_tag(read)?),
Methodref::TAG => visitor.on_method(index, Methodref::read_after_tag(read)?),
InterfaceMethodref::TAG => visitor.on_interface_method(index, InterfaceMethodref::read_after_tag(read)?),
String::TAG => visitor.on_string(index, String::read_after_tag(read)?),
Integer::TAG => visitor.on_integer(index, Integer::read_after_tag(read)?),
Float::TAG => visitor.on_float(index, Float::read_after_tag(read)?),
Long::TAG => {
visitor.on_long(index, Long::read_after_tag(read)?);
index += 1;
visitor.on_unused(index, UnusedPlaceholder {});
},
Double::TAG => {
visitor.on_double(index, Double::read_after_tag(read)?);
index += 1;
visitor.on_unused(index, UnusedPlaceholder {});
},
NameAndType::TAG => visitor.on_name_and_tag(index, NameAndType::read_after_tag(read)?),
Utf8::TAG => visitor.on_utf8(index, Utf8::read_after_tag(read)?),
MethodHandle::TAG => visitor.on_method_handle(index, MethodHandle::read_after_tag(read)?),
MethodType::TAG => visitor.on_method_type(index, MethodType::read_after_tag(read)?),
InvokeDynamic::TAG => visitor.on_invoke_dynamic(index, InvokeDynamic::read_after_tag(read)?),
_ => {
return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Expected CONSTANT_* value reading constant pool, got {:?}", tag)));
},
}
index += 1;
}
Ok(())
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)] pub struct Type(u8);
impl From<u8> for Type {
fn from(value: u8) -> Self {
Self(value)
}
}
pub trait Visitor {
fn on_unused (&mut self, _index: u16, _unused: UnusedPlaceholder) {}
fn on_class (&mut self, _index: u16, _class: Class) {}
fn on_field (&mut self, _index: u16, _field: Fieldref) {}
fn on_method (&mut self, _index: u16, _method: Methodref) {}
fn on_interface_method (&mut self, _index: u16, _interface_method: InterfaceMethodref) {}
fn on_string (&mut self, _index: u16, _string: String) {}
fn on_integer (&mut self, _index: u16, _integer: Integer) {}
fn on_float (&mut self, _index: u16, _float: Float) {}
fn on_long (&mut self, _index: u16, _long: Long) {}
fn on_double (&mut self, _index: u16, _double: Double) {}
fn on_name_and_tag (&mut self, _index: u16, _name_and_tag: NameAndType) {}
fn on_utf8 (&mut self, _index: u16, _utf8: Utf8) {}
fn on_method_handle (&mut self, _index: u16, _method_handle: MethodHandle) {}
fn on_method_type (&mut self, _index: u16, _method_type: MethodType) {}
fn on_invoke_dynamic (&mut self, _index: u16, _invoke_dynamic: InvokeDynamic) {}
}
#[derive(Clone, Debug)] pub struct UnusedPlaceholder {}
#[derive(Clone, Debug)] pub struct Class { pub name_index: u16 }
#[derive(Clone, Debug)] pub struct Fieldref { pub class_index: u16, pub name_and_type_index: u16 }
#[derive(Clone, Debug)] pub struct Methodref { pub class_index: u16, pub name_and_type_index: u16 }
#[derive(Clone, Debug)] pub struct InterfaceMethodref { pub class_index: u16, pub name_and_type_index: u16 }
#[derive(Clone, Debug)] pub struct String { pub string_index: u16 }
#[derive(Clone, Debug)] pub struct Integer ( pub i32 );
#[derive(Clone, Debug)] pub struct Float ( pub f32 );
#[derive(Clone, Debug)] pub struct Long ( pub i64 ); #[derive(Clone, Debug)] pub struct Double ( pub f64 ); #[derive(Clone, Debug)] pub struct NameAndType { pub name_index: u16, pub descriptor_index: u16 }
#[derive(Clone, Debug)] pub struct Utf8 ( pub std::string::String ); #[derive(Clone, Debug)] pub struct MethodHandle { pub reference_kind: u8, pub reference_index: u16 }
#[derive(Clone, Debug)] pub struct MethodType { pub descriptor_index: u16 }
#[derive(Clone, Debug)] pub struct InvokeDynamic { pub bootstrap_method_attr_index: u16, pub name_and_type_index: u16 }
impl Class { pub const TAG : Type = Type( 7); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ name_index: read_u2(r)? })} }
impl Fieldref { pub const TAG : Type = Type( 9); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ class_index: read_u2(r)?, name_and_type_index: read_u2(r)? })} }
impl Methodref { pub const TAG : Type = Type(10); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ class_index: read_u2(r)?, name_and_type_index: read_u2(r)? })} }
impl InterfaceMethodref { pub const TAG : Type = Type(11); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ class_index: read_u2(r)?, name_and_type_index: read_u2(r)? })} }
impl String { pub const TAG : Type = Type( 8); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ string_index: read_u2(r)? })} }
impl Integer { pub const TAG : Type = Type( 3); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self( read_i4(r)? ))} }
impl Float { pub const TAG : Type = Type( 4); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self( f32::from_bits(read_u4(r)?) ))} }
impl Long { pub const TAG : Type = Type( 5); pub const ENTRIES : u8 = 2; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self( read_i8(r)? ))} }
impl Double { pub const TAG : Type = Type( 6); pub const ENTRIES : u8 = 2; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self( f64::from_bits(read_u8(r)?) ))} }
impl NameAndType { pub const TAG : Type = Type(12); pub const ENTRIES : u8 = 2; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ name_index: read_u2(r)?, descriptor_index: read_u2(r)? })} }
impl Utf8 { pub const TAG : Type = Type( 1); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> { Self::read_after_tag_impl(r) } }
impl MethodHandle { pub const TAG : Type = Type(15); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ reference_kind: read_u1(r)?, reference_index: read_u2(r)? })} }
impl MethodType { pub const TAG : Type = Type(16); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ descriptor_index: read_u2(r)? })} }
impl InvokeDynamic { pub const TAG : Type = Type(18); pub const ENTRIES : u8 = 1; pub fn read_after_tag(r: &mut impl Read) -> io::Result<Self> {Ok(Self{ bootstrap_method_attr_index: read_u2(r)?, name_and_type_index: read_u2(r)? })} }
impl Utf8 {
fn expect_byte(remaining: &[u8], index: usize, mask: u8, equal: u8) -> io::Result<u8> {
if let Some(&value) = remaining.get(index) {
if value & mask == equal {
return Ok(value & !mask);
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, format!("Invalid 'UTF8' string - expected index {} byte {:b} & mask {:b} == {:b}", index, value, mask, equal)))
}
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "Incomplete 'UTF8' string - expected more bytes"))
}
}
fn read_char(remaining: &mut &[u8]) -> io::Result<char> {
if let Some(&b0) = remaining.get(0) {
if b0 & 0b10000000 == 0b00000000 {
*remaining = &remaining[1..];
Ok(b0 as char)
} else if b0 & 0b11100000 == 0b11000000 {
let b0 = (b0 & 0b00011111) as u32;
let b1 = Self::expect_byte(*remaining, 1, 0b11000000, 0b10000000)? as u32;
*remaining = &remaining[2..];
Ok(char::try_from(b0 << 6 | b1 << 0).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Expected 'UTF8' bytes"))?)
} else if b0 == 0b11011101 {
let a = Self::expect_byte(*remaining, 1, 0b11110000, 0b10100000)? as u32; let b = Self::expect_byte(*remaining, 2, 0b11000000, 0b10000000)? as u32; let _ = Self::expect_byte(*remaining, 3, 0b11111111, 0b11101101)? as u32; let c = Self::expect_byte(*remaining, 4, 0b11110000, 0b10110000)? as u32; let d = Self::expect_byte(*remaining, 5, 0b11000000, 0b10000000)? as u32; *remaining = &remaining[6..];
Ok(char::try_from(a << 16 | b << 10 | c << 6 | d << 0).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Expected 'UTF8' bytes"))?)
} else if b0 & 0b11110000 == 0b11100000 {
let b0 = (b0 & 0b00001111) as u32;
let b1 = Self::expect_byte(*remaining, 1, 0b11000000, 0b10000000)? as u32;
let b2 = Self::expect_byte(*remaining, 2, 0b11000000, 0b10000000)? as u32;
*remaining = &remaining[3..];
Ok(char::try_from(b0 << 12 | b1 << 6 | b2 << 0).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Expected 'UTF8' bytes"))?)
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "Expected 'UTF8' bytes, invalid starting byte"))
}
} else {
Err(io::Error::new(io::ErrorKind::InvalidData, "Expected 'UTF8' bytes"))
}
}
fn read_after_tag_impl(r: &mut impl Read) -> io::Result<Self> {
let bytes = read_u2(r)? as usize;
let mut buffer = Vec::new();
buffer.resize(bytes, 0u8);
r.read_exact(&mut buffer[..])?;
let mut remaining = &buffer[..];
let mut output = std::string::String::new();
while !remaining.is_empty() {
output.push(Self::read_char(&mut remaining)?);
}
Ok(Self(output))
}
}
#[derive(Clone, Debug)]
pub enum Constant {
UnusedPlaceholder(UnusedPlaceholder),
Class(Class),
Fieldref(Fieldref),
Methodref(Methodref),
InterfaceMethodref(InterfaceMethodref),
String(String),
Integer(Integer),
Float(Float),
Long(Long),
Double(Double),
NameAndType(NameAndType),
Utf8(Utf8),
MethodHandle(MethodHandle),
MethodType(MethodType),
InvokeDynamic(InvokeDynamic),
}
impl From<UnusedPlaceholder> for Constant { fn from(value: UnusedPlaceholder ) -> Self { Constant::UnusedPlaceholder(value) } }
impl From<Class> for Constant { fn from(value: Class ) -> Self { Constant::Class(value) } }
impl From<Fieldref> for Constant { fn from(value: Fieldref ) -> Self { Constant::Fieldref(value) } }
impl From<Methodref> for Constant { fn from(value: Methodref ) -> Self { Constant::Methodref(value) } }
impl From<InterfaceMethodref> for Constant { fn from(value: InterfaceMethodref ) -> Self { Constant::InterfaceMethodref(value) } }
impl From<String> for Constant { fn from(value: String ) -> Self { Constant::String(value) } }
impl From<Integer> for Constant { fn from(value: Integer ) -> Self { Constant::Integer(value) } }
impl From<Float> for Constant { fn from(value: Float ) -> Self { Constant::Float(value) } }
impl From<Long> for Constant { fn from(value: Long ) -> Self { Constant::Long(value) } }
impl From<Double> for Constant { fn from(value: Double ) -> Self { Constant::Double(value) } }
impl From<NameAndType> for Constant { fn from(value: NameAndType ) -> Self { Constant::NameAndType(value) } }
impl From<Utf8> for Constant { fn from(value: Utf8 ) -> Self { Constant::Utf8(value) } }
impl From<MethodHandle> for Constant { fn from(value: MethodHandle ) -> Self { Constant::MethodHandle(value) } }
impl From<MethodType> for Constant { fn from(value: MethodType ) -> Self { Constant::MethodType(value) } }
impl From<InvokeDynamic> for Constant { fn from(value: InvokeDynamic ) -> Self { Constant::InvokeDynamic(value) } }