java_asm 0.1.3

Java bytecode reader & writer in rust
Documentation
pub use raw::*;
pub mod element;

use crate::dex::element::{AsElement, ClassContentElement};
use crate::impls::jvms::r::{ReadContext, ReadFrom, U32BasedSize};
use crate::impls::ToArc;
use crate::smali::SmaliNode;
use crate::{AsmErr, AsmResult, StrRef};
pub use constant::*;
use std::io::Read;
pub use util::*;

pub mod insn;
pub mod insn_syntax;

mod raw;
mod constant;
mod util;

pub type Opcode = u8;

impl DexFile {
    pub fn resolve_from_read<T: Read>(reader: T) -> AsmResult<Self> {
        let mut reader = reader;
        let mut bytes = vec![];
        reader.read_to_end(&mut bytes)
            .map_err(|e| AsmErr::IOReadErr(e.arc()))?;
        Self::resolve_from_bytes(&bytes)
    }
    pub fn resolve_from_bytes(bytes: &[u8]) -> AsmResult<Self> {
        let mut context = ReadContext::little_endian(bytes);
        DexFile::read_from(&mut context)
    }
}

pub struct DexFileAccessor {
    pub file: DexFile,
    pub file_name: StrRef,
    pub bytes: Vec<u8>,
    pub endian: bool,
    pub call_site_ids: Vec<CallSiteId>,
    pub method_handles: Vec<MethodHandle>,
}

impl DexFileAccessor {
    pub fn new(file: DexFile, bytes: Vec<u8>, file_name: StrRef) -> Self {
        let endian = file.header.endian_tag == Header::BIG_ENDIAN_TAG;
        let map_list = Self::get_map_list(&bytes, &file.header, endian)
            .unwrap_or_default();
        let mut call_site_off = 0u32;
        let mut call_site_size = U32BasedSize::default();
        let mut method_handle_off = 0u32;
        let mut method_handle_size = U32BasedSize::default();
        for map_item in map_list.items {
            match map_item.type_value {
                MapListTypeConst::TYPE_CALL_SITE_ID_ITEM => {
                    call_site_off = map_item.offset;
                    call_site_size = map_item.size;
                }
                MapListTypeConst::TYPE_METHOD_HANDLE_ITEM => {
                    method_handle_off = map_item.offset;
                    method_handle_size = map_item.size;
                }
                _ => {}
            }
        }
        let call_site_ids = Self::get_call_site_ids(&bytes, call_site_off, call_site_size, endian);
        let method_handles = Self::get_method_handles(&bytes, method_handle_off, method_handle_size, endian);
        Self { file, bytes, endian, call_site_ids, method_handles, file_name }
    }

    pub fn get_class_element(&self, class_data_off: DUInt) -> AsmResult<ClassContentElement> {
        self.get_data_impl::<ClassDataItem>(class_data_off)?.to_element(&self)
    }

    pub fn get_class_smali(&self, class_def: ClassDef) -> AsmResult<SmaliNode> {
        class_def.to_smali(&self)
    }

    pub fn get_code_item(&self, code_off: DUInt) -> AsmResult<Option<CodeItem>> {
        if code_off == 0 { return Ok(None); }
        self.get_data_impl(code_off).map(Some)
    }
}