refactor values repr
This commit is contained in:
parent
1bf328d44e
commit
b2c4da413c
5 changed files with 740 additions and 720 deletions
371
androscalpel/src/dex_id.rs
Normal file
371
androscalpel/src/dex_id.rs
Normal file
|
|
@ -0,0 +1,371 @@
|
||||||
|
//! The class identifying dex structure.
|
||||||
|
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
use crate::DexString;
|
||||||
|
use androscalpel_serializer::{StringDataItem, Uleb128};
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct IdMethodType {
|
||||||
|
/// Type formated as described by <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||||
|
pub(crate) shorty: DexString,
|
||||||
|
pub(crate) return_type: IdType,
|
||||||
|
pub(crate) parameters: Vec<IdType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
/// The type of a method. The shorty is formated as described in
|
||||||
|
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||||
|
impl IdMethodType {
|
||||||
|
#[new]
|
||||||
|
pub fn new(return_type: IdType, parameters: Vec<IdType>) -> Self {
|
||||||
|
// TODO: check format
|
||||||
|
Self {
|
||||||
|
shorty: Self::get_shorty(&return_type, ¶meters),
|
||||||
|
return_type,
|
||||||
|
parameters,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
let repr: String = (&self.shorty).into();
|
||||||
|
format!("DexMethodType({repr})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdMethodType {
|
||||||
|
/// Compute the format for the shorty as described in
|
||||||
|
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||||
|
pub fn get_shorty(return_type: &IdType, parameters: &[IdType]) -> DexString {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct IdMethodHandle(pub u32);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexMethodHandle {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: u32) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexMethodHandle({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// A type.
|
||||||
|
/// Type represented by [`DexString`] that follow the TypeDescriptor format
|
||||||
|
/// as described here <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct IdType(pub(crate) DexString);
|
||||||
|
#[pymethods]
|
||||||
|
impl IdType {
|
||||||
|
#[new]
|
||||||
|
pub fn _new(ty: DexString) -> Self {
|
||||||
|
// TODO: check format
|
||||||
|
Self(ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the void type (for return type)
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn void() -> Self {
|
||||||
|
Self("V".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the boolean type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn boolean() -> Self {
|
||||||
|
Self("Z".into())
|
||||||
|
}
|
||||||
|
/// Return the byte type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn byte() -> Self {
|
||||||
|
Self("B".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the short type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn short() -> Self {
|
||||||
|
Self("S".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the char type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn char() -> Self {
|
||||||
|
Self("C".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the int type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn int() -> Self {
|
||||||
|
Self("I".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the long type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn long() -> Self {
|
||||||
|
Self("J".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the float type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn float() -> Self {
|
||||||
|
Self("F".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the double type
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn double() -> Self {
|
||||||
|
Self("D".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the type for the class of fully qualified name `name`
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn class(name: &str) -> Self {
|
||||||
|
Self(format!("L{name}").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the type for an array of the specify `type_`
|
||||||
|
#[staticmethod]
|
||||||
|
pub fn array(type_: &IdType) -> Self {
|
||||||
|
let mut ty = type_.clone();
|
||||||
|
ty.0 .0.utf16_size.0 += 1;
|
||||||
|
ty.0 .0.data.insert(0, 0x5b);
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_name(&self) -> DexString {
|
||||||
|
self.0.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
(&self.0).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
let name: String = (&self.0).into();
|
||||||
|
format!("DexType({name})")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is void (return type)
|
||||||
|
pub fn is_void(&self) -> bool {
|
||||||
|
self == &Self::void()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is boolean
|
||||||
|
pub fn is_boolean(&self) -> bool {
|
||||||
|
self == &Self::boolean()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is byte
|
||||||
|
pub fn is_byte(&self) -> bool {
|
||||||
|
self == &Self::byte()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is short
|
||||||
|
pub fn is_short(&self) -> bool {
|
||||||
|
self == &Self::short()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is char
|
||||||
|
pub fn is_char(&self) -> bool {
|
||||||
|
self == &Self::char()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is int
|
||||||
|
pub fn is_int(&self) -> bool {
|
||||||
|
self == &Self::int()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is long
|
||||||
|
pub fn is_long(&self) -> bool {
|
||||||
|
self == &Self::long()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is float
|
||||||
|
pub fn is_float(&self) -> bool {
|
||||||
|
self == &Self::float()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is double
|
||||||
|
pub fn is_double(&self) -> bool {
|
||||||
|
self == &Self::double()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is a class
|
||||||
|
pub fn is_class(&self) -> bool {
|
||||||
|
self.0.get_utf16_size() == 0
|
||||||
|
&& self.0.get_bytes().is_empty()
|
||||||
|
&& self.0.get_bytes()[0] != 0x76
|
||||||
|
// Check if first char is an L
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the type is an array
|
||||||
|
pub fn is_array(&self) -> bool {
|
||||||
|
self.0.get_utf16_size() == 0
|
||||||
|
&& self.0.get_bytes().is_empty()
|
||||||
|
&& self.0.get_bytes()[0] != 0x5b
|
||||||
|
// Check if first char is an [
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the type is a class, return the name of the class,
|
||||||
|
/// else None.
|
||||||
|
pub fn get_class_name(&self) -> Option<DexString> {
|
||||||
|
if self.is_class() {
|
||||||
|
Some(
|
||||||
|
StringDataItem {
|
||||||
|
utf16_size: Uleb128(self.0.get_utf16_size() - 1),
|
||||||
|
data: self.0.get_bytes()[1..].to_vec(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the type is a array, return the type of the elements,
|
||||||
|
/// else None.
|
||||||
|
pub fn get_element_type(&self) -> Option<Self> {
|
||||||
|
if self.is_array() {
|
||||||
|
Some(Self(
|
||||||
|
StringDataItem {
|
||||||
|
utf16_size: Uleb128(self.0.get_utf16_size() - 1),
|
||||||
|
data: self.0.get_bytes()[1..].to_vec(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: TESTS
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct IdField {
|
||||||
|
/// The name of the field, format described at
|
||||||
|
/// <https://source.android.com/docs/core/runtime/dex-format#membername>
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub name: DexString,
|
||||||
|
/// The type of the field.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub type_: IdType,
|
||||||
|
/// The class that own the field.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub class_: IdType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymethods]
|
||||||
|
impl IdField {
|
||||||
|
#[new]
|
||||||
|
pub fn new(name: DexString, type_: IdType, class_: IdType) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
type_,
|
||||||
|
class_,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
let class: String = self.class_.get_name().into();
|
||||||
|
let name: String = (&self.name).into();
|
||||||
|
format!("{class}.{name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
let class: String = self.class_.get_name().into();
|
||||||
|
let name: String = (&self.name).into();
|
||||||
|
format!("IdField({class}.{name})")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct IdMethod(pub u32);
|
||||||
|
#[pymethods]
|
||||||
|
impl IdMethod {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: u32) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexMethod({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct IdEnum(pub u32);
|
||||||
|
#[pymethods]
|
||||||
|
impl IdEnum {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: u32) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexEnum({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct IdAnnotation;
|
||||||
|
#[pymethods]
|
||||||
|
impl IdAnnotation {
|
||||||
|
#[new]
|
||||||
|
pub fn _new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
"DexAnnotation".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
//! Representation of the fields of a class.
|
//! Representation of the fields of a class.
|
||||||
|
|
||||||
use pyo3::exceptions::PyTypeError;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::DexString;
|
use crate::{DexValue, IdField};
|
||||||
use androscalpel_serializer::{StringDataItem, Uleb128};
|
|
||||||
|
|
||||||
/// Represent a field.
|
/// Represent a field.
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
|
@ -12,7 +10,7 @@ use androscalpel_serializer::{StringDataItem, Uleb128};
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
/// The structure used to reference this field.
|
/// The structure used to reference this field.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub descriptor: DexField,
|
pub descriptor: IdField,
|
||||||
/// The field visibility
|
/// The field visibility
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub visibility: FieldVisibility,
|
pub visibility: FieldVisibility,
|
||||||
|
|
@ -51,7 +49,7 @@ pub enum FieldVisibility {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Field {
|
impl Field {
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new(descriptor: DexField) -> Self {
|
pub fn new(descriptor: IdField) -> Self {
|
||||||
Self {
|
Self {
|
||||||
descriptor,
|
descriptor,
|
||||||
visibility: FieldVisibility::Public,
|
visibility: FieldVisibility::Public,
|
||||||
|
|
@ -116,713 +114,3 @@ impl Field {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexByte(pub i8);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexByte {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: i8) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> i8 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexByte({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexShort(pub i16);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexShort {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: i16) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> i16 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexShort({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexChar(pub u16);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexChar {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: u16) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> u16 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexChar({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexInt(pub i32);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexInt {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: i32) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> i32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexInt({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexLong(pub i64);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexLong {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: i64) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> i64 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexLong({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct DexFloat(pub f32);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexFloat {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: f32) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> f32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexFloat({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub struct DexDouble(pub f64);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexDouble {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: f64) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> f64 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexDouble({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct DexMethodType {
|
|
||||||
/// Type formated as described by <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
|
||||||
pub(crate) shorty: DexString,
|
|
||||||
pub(crate) return_type: DexType,
|
|
||||||
pub(crate) parameters: Vec<DexType>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
/// The type of a method. The shorty is formated as described in
|
|
||||||
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
|
||||||
impl DexMethodType {
|
|
||||||
#[new]
|
|
||||||
pub fn new(return_type: DexType, parameters: Vec<DexType>) -> Self {
|
|
||||||
// TODO: check format
|
|
||||||
Self {
|
|
||||||
shorty: Self::get_shorty(&return_type, ¶meters),
|
|
||||||
return_type,
|
|
||||||
parameters,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
let repr: String = (&self.shorty).into();
|
|
||||||
format!("DexMethodType({repr})")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DexMethodType {
|
|
||||||
/// Compute the format for the shorty as described in
|
|
||||||
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
|
||||||
pub fn get_shorty(return_type: &DexType, parameters: &[DexType]) -> DexString {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexMethodHandle(pub u32);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexMethodHandle {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: u32) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> u32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexMethodHandle({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexString(pub u32);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexString {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: u32) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> u32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexString({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// A type.
|
|
||||||
/// Type a represented by [`DexString`] that follow the TypeDescriptor format
|
|
||||||
/// as described here <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct DexType(pub(crate) DexString);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexType {
|
|
||||||
#[new]
|
|
||||||
pub fn _new(ty: DexString) -> Self {
|
|
||||||
// TODO: check format
|
|
||||||
Self(ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the void type (for return type)
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn void() -> Self {
|
|
||||||
Self("V".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the boolean type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn boolean() -> Self {
|
|
||||||
Self("Z".into())
|
|
||||||
}
|
|
||||||
/// Return the byte type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn byte() -> Self {
|
|
||||||
Self("B".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the short type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn short() -> Self {
|
|
||||||
Self("S".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the char type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn char() -> Self {
|
|
||||||
Self("C".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the int type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn int() -> Self {
|
|
||||||
Self("I".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the long type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn long() -> Self {
|
|
||||||
Self("J".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the float type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn float() -> Self {
|
|
||||||
Self("F".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the double type
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn double() -> Self {
|
|
||||||
Self("D".into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the type for the class of fully qualified name `name`
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn class(name: &str) -> Self {
|
|
||||||
Self(format!("L{name}").into())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the type for an array of the specify `type_`
|
|
||||||
#[staticmethod]
|
|
||||||
pub fn array(type_: &DexType) -> Self {
|
|
||||||
let mut ty = type_.clone();
|
|
||||||
ty.0 .0.utf16_size.0 += 1;
|
|
||||||
ty.0 .0.data.insert(0, 0x5b);
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_name(&self) -> DexString {
|
|
||||||
self.0.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
(&self.0).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
let name: String = (&self.0).into();
|
|
||||||
format!("DexType({name})")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is void (return type)
|
|
||||||
pub fn is_void(&self) -> bool {
|
|
||||||
self == &Self::void()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is boolean
|
|
||||||
pub fn is_boolean(&self) -> bool {
|
|
||||||
self == &Self::boolean()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is byte
|
|
||||||
pub fn is_byte(&self) -> bool {
|
|
||||||
self == &Self::byte()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is short
|
|
||||||
pub fn is_short(&self) -> bool {
|
|
||||||
self == &Self::short()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is char
|
|
||||||
pub fn is_char(&self) -> bool {
|
|
||||||
self == &Self::char()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is int
|
|
||||||
pub fn is_int(&self) -> bool {
|
|
||||||
self == &Self::int()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is long
|
|
||||||
pub fn is_long(&self) -> bool {
|
|
||||||
self == &Self::long()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is float
|
|
||||||
pub fn is_float(&self) -> bool {
|
|
||||||
self == &Self::float()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is double
|
|
||||||
pub fn is_double(&self) -> bool {
|
|
||||||
self == &Self::double()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is a class
|
|
||||||
pub fn is_class(&self) -> bool {
|
|
||||||
self.0.get_utf16_size() == 0
|
|
||||||
&& self.0.get_bytes().is_empty()
|
|
||||||
&& self.0.get_bytes()[0] != 0x76
|
|
||||||
// Check if first char is an L
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if the type is an array
|
|
||||||
pub fn is_array(&self) -> bool {
|
|
||||||
self.0.get_utf16_size() == 0
|
|
||||||
&& self.0.get_bytes().is_empty()
|
|
||||||
&& self.0.get_bytes()[0] != 0x5b
|
|
||||||
// Check if first char is an [
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If the type is a class, return the name of the class,
|
|
||||||
/// else None.
|
|
||||||
pub fn get_class_name(&self) -> Option<DexString> {
|
|
||||||
if self.is_class() {
|
|
||||||
Some(
|
|
||||||
StringDataItem {
|
|
||||||
utf16_size: Uleb128(self.0.get_utf16_size() - 1),
|
|
||||||
data: self.0.get_bytes()[1..].to_vec(),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If the type is a array, return the type of the elements,
|
|
||||||
/// else None.
|
|
||||||
pub fn get_element_type(&self) -> Option<Self> {
|
|
||||||
if self.is_array() {
|
|
||||||
Some(Self(
|
|
||||||
StringDataItem {
|
|
||||||
utf16_size: Uleb128(self.0.get_utf16_size() - 1),
|
|
||||||
data: self.0.get_bytes()[1..].to_vec(),
|
|
||||||
}
|
|
||||||
.into(),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: TESTS
|
|
||||||
// TODO: move to another mod
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub struct DexField {
|
|
||||||
/// The name of the field, format described at
|
|
||||||
/// <https://source.android.com/docs/core/runtime/dex-format#membername>
|
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub name: DexString,
|
|
||||||
/// The type of the field.
|
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub type_: DexType,
|
|
||||||
/// The class that own the field.
|
|
||||||
#[pyo3(get, set)]
|
|
||||||
pub class_: DexType,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pymethods]
|
|
||||||
impl DexField {
|
|
||||||
#[new]
|
|
||||||
pub fn new(name: DexString, type_: DexType, class_: DexType) -> Self {
|
|
||||||
Self {
|
|
||||||
name,
|
|
||||||
type_,
|
|
||||||
class_,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
let class: String = self.class_.get_name().into();
|
|
||||||
let name: String = (&self.name).into();
|
|
||||||
format!("{class}.{name}")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
let class: String = self.class_.get_name().into();
|
|
||||||
let name: String = (&self.name).into();
|
|
||||||
format!("DexField({class}.{name})")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexMethod(pub u32);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexMethod {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: u32) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> u32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexMethod({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexEnum(pub u32);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexEnum {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: u32) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> u32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexEnum({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexArray;
|
|
||||||
#[pymethods]
|
|
||||||
impl DexArray {
|
|
||||||
#[new]
|
|
||||||
pub fn _new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
"DexArray".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexAnnotation;
|
|
||||||
#[pymethods]
|
|
||||||
impl DexAnnotation {
|
|
||||||
#[new]
|
|
||||||
pub fn _new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
"DexAnnotation".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexNull;
|
|
||||||
#[pymethods]
|
|
||||||
impl DexNull {
|
|
||||||
#[new]
|
|
||||||
pub fn _new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
"DexNull".into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pyclass]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub struct DexBoolean(pub bool);
|
|
||||||
#[pymethods]
|
|
||||||
impl DexBoolean {
|
|
||||||
#[new]
|
|
||||||
pub fn new(val: bool) -> Self {
|
|
||||||
Self(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_value(&self) -> bool {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __str__(&self) -> String {
|
|
||||||
self.__repr__()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn __repr__(&self) -> String {
|
|
||||||
format!("DexBoolean({})", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum DexValue {
|
|
||||||
Byte(DexByte),
|
|
||||||
Short(DexShort),
|
|
||||||
Char(DexChar),
|
|
||||||
Int(DexInt),
|
|
||||||
Long(DexLong),
|
|
||||||
Float(DexFloat),
|
|
||||||
Double(DexDouble),
|
|
||||||
MethodType(DexMethodType),
|
|
||||||
//MethodHandle(DexMethodHandle),
|
|
||||||
String(DexString),
|
|
||||||
Type(DexType),
|
|
||||||
Field(DexField),
|
|
||||||
Method(DexMethod),
|
|
||||||
Enum(DexEnum),
|
|
||||||
Array(DexArray),
|
|
||||||
Annotation(DexAnnotation),
|
|
||||||
Null(DexNull),
|
|
||||||
Boolean(DexBoolean),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'source> FromPyObject<'source> for DexValue {
|
|
||||||
fn extract(ob: &'source PyAny) -> PyResult<Self> {
|
|
||||||
if let Ok(val) = DexByte::extract(ob) {
|
|
||||||
Ok(Self::Byte(val))
|
|
||||||
} else if let Ok(val) = DexShort::extract(ob) {
|
|
||||||
Ok(Self::Short(val))
|
|
||||||
} else if let Ok(val) = DexChar::extract(ob) {
|
|
||||||
Ok(Self::Char(val))
|
|
||||||
} else if let Ok(val) = DexInt::extract(ob) {
|
|
||||||
Ok(Self::Int(val))
|
|
||||||
} else if let Ok(val) = DexLong::extract(ob) {
|
|
||||||
Ok(Self::Long(val))
|
|
||||||
} else if let Ok(val) = DexFloat::extract(ob) {
|
|
||||||
Ok(Self::Float(val))
|
|
||||||
} else if let Ok(val) = DexDouble::extract(ob) {
|
|
||||||
Ok(Self::Double(val))
|
|
||||||
} else if let Ok(val) = DexString::extract(ob) {
|
|
||||||
Ok(Self::String(val))
|
|
||||||
} else if let Ok(val) = DexType::extract(ob) {
|
|
||||||
Ok(Self::Type(val))
|
|
||||||
} else if let Ok(val) = DexField::extract(ob) {
|
|
||||||
Ok(Self::Field(val))
|
|
||||||
} else if let Ok(val) = DexMethod::extract(ob) {
|
|
||||||
Ok(Self::Method(val))
|
|
||||||
} else if let Ok(val) = DexEnum::extract(ob) {
|
|
||||||
Ok(Self::Enum(val))
|
|
||||||
} else if let Ok(val) = DexArray::extract(ob) {
|
|
||||||
Ok(Self::Array(val))
|
|
||||||
} else if let Ok(val) = DexAnnotation::extract(ob) {
|
|
||||||
Ok(Self::Annotation(val))
|
|
||||||
} else if let Ok(val) = DexNull::extract(ob) {
|
|
||||||
Ok(Self::Null(val))
|
|
||||||
} else if let Ok(val) = DexBoolean::extract(ob) {
|
|
||||||
Ok(Self::Boolean(val))
|
|
||||||
} else if let Ok(val) = DexMethodType::extract(ob) {
|
|
||||||
Ok(Self::MethodType(val))
|
|
||||||
// } else if let Ok(val) = DexMethodHandle::extract(ob) { Ok(Self::MethodHandle(val))
|
|
||||||
} else {
|
|
||||||
Err(PyErr::new::<PyTypeError, _>(format!(
|
|
||||||
"{} is not a castable as a DexValue",
|
|
||||||
ob.repr()?
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoPy<PyObject> for DexValue {
|
|
||||||
fn into_py(self, py: Python<'_>) -> PyObject {
|
|
||||||
match self {
|
|
||||||
DexValue::Byte(val) => val.into_py(py),
|
|
||||||
DexValue::Short(val) => val.into_py(py),
|
|
||||||
DexValue::Char(val) => val.into_py(py),
|
|
||||||
DexValue::Int(val) => val.into_py(py),
|
|
||||||
DexValue::Long(val) => val.into_py(py),
|
|
||||||
DexValue::Float(val) => val.into_py(py),
|
|
||||||
DexValue::Double(val) => val.into_py(py),
|
|
||||||
DexValue::MethodType(val) => val.into_py(py),
|
|
||||||
//DexValue::MethodHandle(val) => val.into_py(py),
|
|
||||||
DexValue::String(val) => val.into_py(py),
|
|
||||||
DexValue::Type(val) => val.into_py(py),
|
|
||||||
DexValue::Field(val) => val.into_py(py),
|
|
||||||
DexValue::Method(val) => val.into_py(py),
|
|
||||||
DexValue::Enum(val) => val.into_py(py),
|
|
||||||
DexValue::Array(val) => val.into_py(py),
|
|
||||||
DexValue::Annotation(val) => val.into_py(py),
|
|
||||||
DexValue::Null(val) => val.into_py(py),
|
|
||||||
DexValue::Boolean(val) => val.into_py(py),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,17 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
pub mod apk;
|
pub mod apk;
|
||||||
pub mod class;
|
pub mod class;
|
||||||
|
pub mod dex_id;
|
||||||
pub mod field;
|
pub mod field;
|
||||||
|
pub mod scalar;
|
||||||
|
pub mod value;
|
||||||
|
|
||||||
pub use apk::*;
|
pub use apk::*;
|
||||||
pub use class::*;
|
pub use class::*;
|
||||||
|
pub use dex_id::*;
|
||||||
pub use field::*;
|
pub use field::*;
|
||||||
|
pub use scalar::*;
|
||||||
|
pub use value::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
@ -158,12 +164,12 @@ fn androscalpel(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
// m.add_class::<DexMethodType>()?;
|
// m.add_class::<DexMethodType>()?;
|
||||||
// m.add_class::<DexMethodHandle>()?;
|
// m.add_class::<DexMethodHandle>()?;
|
||||||
m.add_class::<DexString>()?;
|
m.add_class::<DexString>()?;
|
||||||
m.add_class::<DexType>()?;
|
m.add_class::<IdType>()?;
|
||||||
m.add_class::<DexField>()?;
|
m.add_class::<IdField>()?;
|
||||||
m.add_class::<DexMethod>()?;
|
m.add_class::<IdMethod>()?;
|
||||||
m.add_class::<DexEnum>()?;
|
m.add_class::<IdEnum>()?;
|
||||||
m.add_class::<DexArray>()?;
|
m.add_class::<DexArray>()?;
|
||||||
m.add_class::<DexAnnotation>()?;
|
m.add_class::<IdAnnotation>()?;
|
||||||
m.add_class::<DexNull>()?;
|
m.add_class::<DexNull>()?;
|
||||||
m.add_class::<DexBoolean>()?;
|
m.add_class::<DexBoolean>()?;
|
||||||
m.add_class::<DexString>()?;
|
m.add_class::<DexString>()?;
|
||||||
|
|
|
||||||
256
androscalpel/src/scalar.rs
Normal file
256
androscalpel/src/scalar.rs
Normal file
|
|
@ -0,0 +1,256 @@
|
||||||
|
//! The class identifying dex structure.
|
||||||
|
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
// TODO: move DexString here
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexByte(pub i8);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexByte {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: i8) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> i8 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexByte({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexShort(pub i16);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexShort {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: i16) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> i16 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexShort({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexChar(pub u16);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexChar {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: u16) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u16 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexChar({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexInt(pub i32);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexInt {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: i32) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> i32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexInt({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexLong(pub i64);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexLong {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: i64) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> i64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexLong({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct DexFloat(pub f32);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexFloat {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: f32) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> f32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexFloat({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct DexDouble(pub f64);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexDouble {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: f64) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> f64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexDouble({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DexString is already define in lib.rs, TODO: move the version in lib.rs here
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexString(pub u32);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexString {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: u32) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexString({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexNull;
|
||||||
|
#[pymethods]
|
||||||
|
impl DexNull {
|
||||||
|
#[new]
|
||||||
|
pub fn _new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
"DexNull".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexBoolean(pub bool);
|
||||||
|
#[pymethods]
|
||||||
|
impl DexBoolean {
|
||||||
|
#[new]
|
||||||
|
pub fn new(val: bool) -> Self {
|
||||||
|
Self(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> bool {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
format!("DexBoolean({})", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct DexArray;
|
||||||
|
#[pymethods]
|
||||||
|
impl DexArray {
|
||||||
|
#[new]
|
||||||
|
pub fn _new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __str__(&self) -> String {
|
||||||
|
self.__repr__()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn __repr__(&self) -> String {
|
||||||
|
"DexArray".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
99
androscalpel/src/value.rs
Normal file
99
androscalpel/src/value.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
//! The class identifying dex structure.
|
||||||
|
|
||||||
|
use pyo3::exceptions::PyTypeError;
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
use crate::{dex_id::*, scalar::*, DexString};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum DexValue {
|
||||||
|
Byte(DexByte),
|
||||||
|
Short(DexShort),
|
||||||
|
Char(DexChar),
|
||||||
|
Int(DexInt),
|
||||||
|
Long(DexLong),
|
||||||
|
Float(DexFloat),
|
||||||
|
Double(DexDouble),
|
||||||
|
MethodType(IdMethodType),
|
||||||
|
//MethodHandle(DexMethodHandle),
|
||||||
|
String(DexString),
|
||||||
|
Type(IdType),
|
||||||
|
Field(IdField),
|
||||||
|
Method(IdMethod),
|
||||||
|
Enum(IdEnum),
|
||||||
|
Array(DexArray),
|
||||||
|
Annotation(IdAnnotation),
|
||||||
|
Null(DexNull),
|
||||||
|
Boolean(DexBoolean),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'source> FromPyObject<'source> for DexValue {
|
||||||
|
fn extract(ob: &'source PyAny) -> PyResult<Self> {
|
||||||
|
if let Ok(val) = DexByte::extract(ob) {
|
||||||
|
Ok(Self::Byte(val))
|
||||||
|
} else if let Ok(val) = DexShort::extract(ob) {
|
||||||
|
Ok(Self::Short(val))
|
||||||
|
} else if let Ok(val) = DexChar::extract(ob) {
|
||||||
|
Ok(Self::Char(val))
|
||||||
|
} else if let Ok(val) = DexInt::extract(ob) {
|
||||||
|
Ok(Self::Int(val))
|
||||||
|
} else if let Ok(val) = DexLong::extract(ob) {
|
||||||
|
Ok(Self::Long(val))
|
||||||
|
} else if let Ok(val) = DexFloat::extract(ob) {
|
||||||
|
Ok(Self::Float(val))
|
||||||
|
} else if let Ok(val) = DexDouble::extract(ob) {
|
||||||
|
Ok(Self::Double(val))
|
||||||
|
} else if let Ok(val) = DexString::extract(ob) {
|
||||||
|
Ok(Self::String(val))
|
||||||
|
} else if let Ok(val) = IdType::extract(ob) {
|
||||||
|
Ok(Self::Type(val))
|
||||||
|
} else if let Ok(val) = IdField::extract(ob) {
|
||||||
|
Ok(Self::Field(val))
|
||||||
|
} else if let Ok(val) = IdMethod::extract(ob) {
|
||||||
|
Ok(Self::Method(val))
|
||||||
|
} else if let Ok(val) = IdEnum::extract(ob) {
|
||||||
|
Ok(Self::Enum(val))
|
||||||
|
} else if let Ok(val) = DexArray::extract(ob) {
|
||||||
|
Ok(Self::Array(val))
|
||||||
|
} else if let Ok(val) = IdAnnotation::extract(ob) {
|
||||||
|
Ok(Self::Annotation(val))
|
||||||
|
} else if let Ok(val) = DexNull::extract(ob) {
|
||||||
|
Ok(Self::Null(val))
|
||||||
|
} else if let Ok(val) = DexBoolean::extract(ob) {
|
||||||
|
Ok(Self::Boolean(val))
|
||||||
|
} else if let Ok(val) = IdMethodType::extract(ob) {
|
||||||
|
Ok(Self::MethodType(val))
|
||||||
|
// } else if let Ok(val) = DexMethodHandle::extract(ob) { Ok(Self::MethodHandle(val))
|
||||||
|
} else {
|
||||||
|
Err(PyErr::new::<PyTypeError, _>(format!(
|
||||||
|
"{} is not a castable as a DexValue",
|
||||||
|
ob.repr()?
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoPy<PyObject> for DexValue {
|
||||||
|
fn into_py(self, py: Python<'_>) -> PyObject {
|
||||||
|
match self {
|
||||||
|
DexValue::Byte(val) => val.into_py(py),
|
||||||
|
DexValue::Short(val) => val.into_py(py),
|
||||||
|
DexValue::Char(val) => val.into_py(py),
|
||||||
|
DexValue::Int(val) => val.into_py(py),
|
||||||
|
DexValue::Long(val) => val.into_py(py),
|
||||||
|
DexValue::Float(val) => val.into_py(py),
|
||||||
|
DexValue::Double(val) => val.into_py(py),
|
||||||
|
DexValue::MethodType(val) => val.into_py(py),
|
||||||
|
//DexValue::MethodHandle(val) => val.into_py(py),
|
||||||
|
DexValue::String(val) => val.into_py(py),
|
||||||
|
DexValue::Type(val) => val.into_py(py),
|
||||||
|
DexValue::Field(val) => val.into_py(py),
|
||||||
|
DexValue::Method(val) => val.into_py(py),
|
||||||
|
DexValue::Enum(val) => val.into_py(py),
|
||||||
|
DexValue::Array(val) => val.into_py(py),
|
||||||
|
DexValue::Annotation(val) => val.into_py(py),
|
||||||
|
DexValue::Null(val) => val.into_py(py),
|
||||||
|
DexValue::Boolean(val) => val.into_py(py),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue