Skip to main content

lvm_class/constant_pool/
mod.rs

1//! Constant pool types and structures.
2//!
3//! The constant pool is a table of structures representing various string constants,
4//! class and interface names, field names, and other constants that are referred to
5//! within the ClassFile structure and its substructures.
6
7use crate::error::ClassFormatErr;
8
9mod entry;
10mod types;
11
12// Re-export commonly used types at the module level
13pub use entry::{ConstantEntry, ConstantKind};
14pub use types::{Dynamic, MethodHandle, MethodHandleKind, NameAndType, Reference};
15
16/// The constant pool of a class file.
17///
18/// https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.4
19#[derive(Debug, Clone, PartialEq)]
20pub struct ConstantPool {
21    pub inner: Vec<ConstantEntry>,
22}
23
24impl ConstantPool {
25    pub fn get_utf8(&self, idx: &u16) -> Result<&str, ClassFormatErr> {
26        self.inner
27            .get(*idx as usize)
28            .ok_or(ClassFormatErr::ConstantNotFound(*idx))
29            .and_then(|entry| match entry {
30                ConstantEntry::Utf8(value) => Ok(value.as_str()),
31                e => Err(ClassFormatErr::TypeError(
32                    *idx,
33                    ConstantKind::Utf8.to_string(),
34                    e.get_kind().to_string(),
35                )),
36            })
37    }
38
39    pub fn find_utf8(&self, s: &str) -> Option<u16> {
40        self.inner
41            .iter()
42            .enumerate()
43            .find_map(|(idx, entry)| match entry {
44                ConstantEntry::Utf8(value) if value == s => Some(idx as u16),
45                _ => None,
46            })
47    }
48
49    pub fn get_class_name(&self, idx: &u16) -> Result<&str, ClassFormatErr> {
50        let name_index = self.get_class(idx)?;
51        self.get_utf8(&name_index)
52    }
53
54    pub fn get_class(&self, idx: &u16) -> Result<u16, ClassFormatErr> {
55        self.inner
56            .get(*idx as usize)
57            .ok_or(ClassFormatErr::ConstantNotFound(*idx))
58            .and_then(|entry| match entry {
59                ConstantEntry::Class(name_index) => Ok(*name_index),
60                e => Err(ClassFormatErr::TypeError(
61                    *idx,
62                    ConstantKind::Class.to_string(),
63                    e.get_kind().to_string(),
64                )),
65            })
66    }
67}