use super::Reader;
const UTF8: u8 = 1;
const CLASS: u8 = 7;
const LONG: u8 = 5;
const DOUBLE: u8 = 6;
const WIDE: usize = 8;
const SIZES: [(u8, usize); 13] = [
(3, 4), (4, 4), (8, 2), (9, 4), (10, 4), (11, 4), (12, 4), (15, 3), (16, 2), (17, 4), (18, 4), (19, 2), (20, 2), ];
enum Entry {
Utf8(String),
Class(u16),
Other,
}
pub(super) struct Pool {
entries: Vec<Entry>,
}
impl Pool {
pub(super) fn read(r: &mut Reader<'_>) -> Option<Pool> {
let count = r.u16()?;
let mut entries = vec![Entry::Other];
while entries.len() < usize::from(count) {
let tag = r.u8()?;
let entry = match tag {
UTF8 => {
let len = usize::from(r.u16()?);
Entry::Utf8(String::from_utf8_lossy(r.take(len)?).into_owned())
}
CLASS => Entry::Class(r.u16()?),
LONG | DOUBLE => {
r.take(WIDE)?;
entries.push(Entry::Other);
Entry::Other
}
_ => {
let size = SIZES.iter().find(|(t, _)| *t == tag)?.1;
r.take(size)?;
Entry::Other
}
};
entries.push(entry);
}
Some(Pool { entries })
}
pub(super) fn utf8(&self, i: u16) -> Option<&str> {
match self.entries.get(usize::from(i))? {
Entry::Utf8(s) => Some(s),
_ => None,
}
}
pub(super) fn class(&self, i: u16) -> Option<&str> {
match self.entries.get(usize::from(i))? {
Entry::Class(name) => self.utf8(*name),
_ => None,
}
}
}