#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum AttributeErrorKind {
Bytes,
ReservedTag,
TrailingBytes,
CountOverflow,
StaticConstraint,
NestingBudgetExceeded,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AttributeError {
pub kind: AttributeErrorKind,
pub offset: usize,
pub message: String,
}
impl fmt::Display for AttributeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} at byte {}", self.message, self.offset)
}
}
impl std::error::Error for AttributeError {}
impl From<ByteError> for AttributeError {
fn from(value: ByteError) -> Self {
Self {
kind: AttributeErrorKind::Bytes,
offset: value.offset,
message: value.message,
}
}
}
fn error(kind: AttributeErrorKind, offset: usize, message: impl Into<String>) -> AttributeError {
AttributeError {
kind,
offset,
message: message.into(),
}
}
fn finish(reader: &ByteReader<'_>) -> Result<(), AttributeError> {
if reader.remaining() == 0 {
Ok(())
} else {
Err(error(
AttributeErrorKind::TrailingBytes,
reader.offset(),
format!("{} trailing attribute bytes", reader.remaining()),
))
}
}
fn count(value: usize, what: &str) -> Result<u16, AttributeError> {
u16::try_from(value).map_err(|_| {
error(
AttributeErrorKind::CountOverflow,
0,
format!("too many {what}"),
)
})
}
fn read_u2s(reader: &mut ByteReader<'_>, what: &str) -> Result<Vec<u16>, AttributeError> {
let n = usize::from(reader.read_u2()?);
reader.preflight_allocation(n)?;
let mut values = Vec::with_capacity(n);
for _ in 0..n {
values.push(reader.read_u2()?);
}
finish(reader)?;
let _ = what;
Ok(values)
}
fn write_u2s(values: &[u16], budget: usize, what: &str) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u2(count(values.len(), what)?)?;
for value in values {
out.write_u2(*value)?;
}
Ok(out.into_bytes())
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct IndexAttribute {
pub index: u16,
}
impl IndexAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let index = reader.read_u2()?;
finish(reader)?;
Ok(Self { index })
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u2(self.index)?;
Ok(out.into_bytes())
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct MarkerAttribute;
impl MarkerAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
finish(reader)?;
Ok(Self)
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
Ok(ByteWriter::new(budget).into_bytes())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ByteAttribute {
pub bytes: Vec<u8>,
}
impl ByteAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let bytes = reader.take(reader.remaining())?.to_vec();
Ok(Self { bytes })
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_bytes(&self.bytes)?;
Ok(out.into_bytes())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct IndexListAttribute {
pub indices: Vec<u16>,
}
impl IndexListAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
Ok(Self {
indices: read_u2s(reader, "indices")?,
})
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
write_u2s(&self.indices, budget, "indices")
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct InnerClass {
pub inner_class_index: u16,
pub outer_class_index: u16,
pub inner_name_index: u16,
pub access_flags: u16,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InnerClassesAttribute {
pub classes: Vec<InnerClass>,
}
impl InnerClassesAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let n = usize::from(reader.read_u2()?);
reader.preflight_allocation(n)?;
let mut classes = Vec::with_capacity(n);
for _ in 0..n {
classes.push(InnerClass {
inner_class_index: reader.read_u2()?,
outer_class_index: reader.read_u2()?,
inner_name_index: reader.read_u2()?,
access_flags: reader.read_u2()?,
});
}
finish(reader)?;
Ok(Self { classes })
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u2(count(self.classes.len(), "inner classes")?)?;
for v in &self.classes {
out.write_u2(v.inner_class_index)?;
out.write_u2(v.outer_class_index)?;
out.write_u2(v.inner_name_index)?;
out.write_u2(v.access_flags)?;
}
Ok(out.into_bytes())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EnclosingMethodAttribute {
pub class_index: u16,
pub method_index: u16,
}
impl EnclosingMethodAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let class_index = reader.read_u2()?;
let method_index = reader.read_u2()?;
finish(reader)?;
Ok(Self {
class_index,
method_index,
})
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u2(self.class_index)?;
out.write_u2(self.method_index)?;
Ok(out.into_bytes())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct LineNumber {
pub start_pc: u16,
pub line_number: u16,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LineNumberTableAttribute {
pub lines: Vec<LineNumber>,
}
impl LineNumberTableAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let n = usize::from(reader.read_u2()?);
reader.preflight_allocation(n)?;
let mut lines = Vec::with_capacity(n);
for _ in 0..n {
lines.push(LineNumber {
start_pc: reader.read_u2()?,
line_number: reader.read_u2()?,
});
}
finish(reader)?;
Ok(Self { lines })
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u2(count(self.lines.len(), "line numbers")?)?;
for v in &self.lines {
out.write_u2(v.start_pc)?;
out.write_u2(v.line_number)?;
}
Ok(out.into_bytes())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct LocalVariable {
pub start_pc: u16,
pub length: u16,
pub name_index: u16,
pub type_index: u16,
pub slot: u16,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LocalVariablesAttribute {
pub variables: Vec<LocalVariable>,
}
impl LocalVariablesAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let n = usize::from(reader.read_u2()?);
reader.preflight_allocation(n)?;
let mut variables = Vec::with_capacity(n);
for _ in 0..n {
variables.push(LocalVariable {
start_pc: reader.read_u2()?,
length: reader.read_u2()?,
name_index: reader.read_u2()?,
type_index: reader.read_u2()?,
slot: reader.read_u2()?,
});
}
finish(reader)?;
Ok(Self { variables })
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u2(count(self.variables.len(), "local variables")?)?;
for v in &self.variables {
out.write_u2(v.start_pc)?;
out.write_u2(v.length)?;
out.write_u2(v.name_index)?;
out.write_u2(v.type_index)?;
out.write_u2(v.slot)?;
}
Ok(out.into_bytes())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct MethodParameter {
pub name_index: u16,
pub access_flags: u16,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MethodParametersAttribute {
pub parameters: Vec<MethodParameter>,
}
impl MethodParametersAttribute {
pub fn decode(reader: &mut ByteReader<'_>) -> Result<Self, AttributeError> {
let n = usize::from(reader.read_u1()?);
reader.preflight_allocation(n)?;
let mut parameters = Vec::with_capacity(n);
for _ in 0..n {
parameters.push(MethodParameter {
name_index: reader.read_u2()?,
access_flags: reader.read_u2()?,
});
}
finish(reader)?;
Ok(Self { parameters })
}
pub fn encode(&self, budget: usize) -> Result<Vec<u8>, AttributeError> {
let mut out = ByteWriter::new(budget);
out.write_u1(u8::try_from(self.parameters.len()).map_err(|_| {
error(
AttributeErrorKind::CountOverflow,
0,
"too many method parameters",
)
})?)?;
for v in &self.parameters {
out.write_u2(v.name_index)?;
out.write_u2(v.access_flags)?;
}
Ok(out.into_bytes())
}
}