diff --git a/src/parse/mod.rs b/src/parse/mod.rs index c880278..3ced475 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -1,3 +1,82 @@ +use crate::parse::model::{u1, u2, u4, ClassFile, CpInfo}; + mod model; -pub fn parse_class_file(data: &[u8]) {} +struct ParseErr; + +struct Data { + data: Vec, + pointer: usize, +} + +impl From> for Data { + fn from(data: Vec) -> Self { + Self { data, pointer: 0 } + } +} + +impl Data { + fn u1(&mut self) -> Result { + let item = self.data.get(self.pointer).cloned(); + self.pointer += 1; + item.ok_or(ParseErr) + } + + fn u2(&mut self) -> Result { + Ok(((self.u1()? as u2) << 8) | self.u1() as u2) + } + + fn u4(&mut self) -> Result { + Ok(((self.u2()? as u4) << 16) | self.u2() as u4) + } + + fn last_u1(&mut self) -> Result { + self.data.get(self.pointer - 1).cloned().ok_or(ParseErr) + } + + fn last_u2(&mut self) -> Result { + let last2u1 = self.data.get(self.pointer - 2).cloned().ok_or(ParseErr); + Ok(((self.last_u1()? as u2) << 8) | last2u1 as u2) + } +} + +pub trait Parse { + fn parse(data: &mut Data) -> Result; +} + +pub trait ParseVec { + fn parse_vec(data: &mut Data, len: usize) -> Result; +} + +impl Parse for ClassFile { + fn parse(data: &mut Data) -> Result { + Ok(Self { + magic: data.u4()?, + minor_version: data.u2()?, + major_version: data.u2()?, + constant_pool_count: data.u2()?, + constant_pool: Vec::parse_vec::(data, data.last_u2() as usize)?, + access_flags: data.u2()?, + this_class: data.u2()?, + super_class: data.u2()?, + interfaces_count: data.u2()?, + interfaces: vec![], + fields_count: 0, + fields: vec![], + method_count: 0, + methods: vec![], + attributes_count: 0, + attributes: vec![], + }) + } +} + +impl ParseVec for Vec { + fn parse_vec(data: &mut Data, len: usize) -> Result { + let mut vec = Vec::with_capacity(len); + for i in 0..len { + vec.push(T::parse(data)?); + } + Ok(vec) + } +}