put pyo3 away for now
This commit is contained in:
parent
ea6ce5d7a1
commit
1c45b9e38b
15 changed files with 248 additions and 215 deletions
|
|
@ -14,8 +14,8 @@ androscalpel_serializer = { version = "0.1.0", path = "../androscalpel_serialize
|
|||
anyhow = { version = "1.0.75", features = ["backtrace"] }
|
||||
apk_frauder = { version = "0.1.0", path = "../apk_frauder" }
|
||||
log = "0.4.20"
|
||||
pyo3 = { version = "0.23.4", features = ["anyhow", "abi3-py38"] }
|
||||
pyo3-log = "0.12.1"
|
||||
pyo3 = { version = "0.23.4", features = ["anyhow", "abi3-py38", "extension-module"], optional = true}
|
||||
pyo3-log = { version = "0.12.1", optional = true}
|
||||
rayon = "1.9.0"
|
||||
serde = { version = "1.0.195", features = ["derive"] }
|
||||
serde_json = "1.0.111"
|
||||
|
|
@ -24,6 +24,7 @@ sha1 = "0.10.6"
|
|||
[dev-dependencies]
|
||||
pretty_assertions = "1.4.1"
|
||||
|
||||
#[features]
|
||||
#extension-module = ["pyo3/extension-module"]
|
||||
#default = [""]
|
||||
[features]
|
||||
default = []
|
||||
# TODO: need refactoring to https://github.com/PyO3/pyo3/issues/2935#issuecomment-2560930677 or cfg_eval https://github.com/rust-lang/rust/issues/82679
|
||||
python = ["pyo3", "pyo3-log"]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::hashmap_vectorize;
|
||||
|
|
@ -11,28 +12,28 @@ use crate::{
|
|||
};
|
||||
|
||||
/// Annotation with a visibility
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct DexAnnotationItem {
|
||||
// TODO: the get/set will probably be wonky on the python side when edditing
|
||||
/// The actual annotation
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub annotation: DexAnnotation,
|
||||
// TODO: enforce exclusivity
|
||||
/// If the annotation visibility is set to build
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub visibility_build: bool,
|
||||
/// If the annotation visibility is set to runtime
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub visibility_runtime: bool,
|
||||
/// If the annotation visibility is set to system
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub visibility_system: bool,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexAnnotationItem {
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(annotation: DexAnnotation) -> Self {
|
||||
Self {
|
||||
annotation,
|
||||
|
|
@ -101,7 +102,7 @@ impl DexAnnotationItem {
|
|||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
|
@ -122,23 +123,23 @@ impl<V: VisitorMut> VisitableMut<V> for DexAnnotationItem {
|
|||
}
|
||||
|
||||
/// An annotation.
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct DexAnnotation {
|
||||
// TODO: check the relation between type and encoded_value.
|
||||
/// The type of the annotation.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub type_: IdType,
|
||||
// TODO: the get/set will probably be wonky on the python side when edditing
|
||||
/// The annotation elements.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
#[serde(with = "hashmap_vectorize")]
|
||||
pub elements: HashMap<DexString, DexValue>, // TODO: check MemberName syntax?
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexAnnotation {
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(type_: IdType, elements: HashMap<DexString, DexValue>) -> Self {
|
||||
Self { type_, elements }
|
||||
}
|
||||
|
|
@ -218,7 +219,7 @@ impl DexAnnotation {
|
|||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use std::io::Cursor;
|
|||
use std::path::PathBuf;
|
||||
|
||||
use log::info;
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::PyBytes;
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::{prelude::*, types::PyBytes};
|
||||
|
||||
use crate::ins::CallSite;
|
||||
use crate::instructions;
|
||||
|
|
@ -32,7 +32,7 @@ pub struct DexFile {
|
|||
}
|
||||
|
||||
/// Represent an apk.
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)]
|
||||
pub struct Apk {
|
||||
pub dex_files: HashMap<String, DexFile>, // TODO: use accessort for chache invalidation
|
||||
|
|
@ -2981,9 +2981,9 @@ impl Apk {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl Apk {
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new() -> Self {
|
||||
// TODO take argument and dispatch to load_apk or load_apk_bin
|
||||
Self {
|
||||
|
|
@ -2993,8 +2993,8 @@ impl Apk {
|
|||
|
||||
/// Load all android files in an application.
|
||||
/// This **does not include any .dex file that android would not load.
|
||||
#[staticmethod]
|
||||
#[pyo3(signature = (apk, label_each_ins=false, cache=false))]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
#[cfg_attr(feature = "python", pyo3(signature = (apk, label_each_ins=false, cache=false)))]
|
||||
pub fn load_apk(apk: PathBuf, label_each_ins: bool, cache: bool) -> Result<Self> {
|
||||
let file = File::open(apk)?;
|
||||
let mut apk_z = ZipFileReader::new(file);
|
||||
|
|
@ -3013,8 +3013,8 @@ impl Apk {
|
|||
|
||||
/// Load all android files in an application.
|
||||
/// This **does not include any .dex file that android would not load.
|
||||
#[staticmethod]
|
||||
#[pyo3(signature = (apk, label_each_ins=false, cache=false))]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
#[cfg_attr(feature = "python", pyo3(signature = (apk, label_each_ins=false, cache=false)))]
|
||||
pub fn load_apk_bin(apk: &[u8], label_each_ins: bool, cache: bool) -> Result<Self> {
|
||||
let mut apk_z = ZipFileReader::new(Cursor::new(apk));
|
||||
let mut apk = Self::default();
|
||||
|
|
@ -3039,7 +3039,7 @@ impl Apk {
|
|||
/// - `label_each_ins`: if set to true, insert a label before each instruction
|
||||
/// indicating the instruction address
|
||||
/// - `cache`: if set to true, copy and cache the binary data format.
|
||||
#[pyo3(signature = (name, data, label_each_ins=false, cache=false))]
|
||||
#[cfg_attr(feature = "python", pyo3(signature = (name, data, label_each_ins=false, cache=false)))]
|
||||
pub fn add_dex_file(
|
||||
&mut self,
|
||||
name: &str,
|
||||
|
|
@ -3096,7 +3096,7 @@ impl Apk {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[pyo3(signature = (method_id, code=None, dex_file=None))]
|
||||
#[cfg_attr(feature = "python", pyo3(signature = (method_id, code=None, dex_file=None)))]
|
||||
pub fn set_method_code(
|
||||
&mut self,
|
||||
method_id: IdMethod,
|
||||
|
|
@ -3131,6 +3131,7 @@ impl Apk {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
#[pyo3(name = "gen_raw_dex")] //Sad GIL noise
|
||||
pub fn py_gen_raw_dex(&self, py: Python<'_>) -> Result<HashMap<String, PyObject>> {
|
||||
Ok(self
|
||||
|
|
@ -3144,12 +3145,12 @@ impl Apk {
|
|||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[pyo3(signature = (class, dex_file=None))]
|
||||
#[cfg_attr(feature = "python", pyo3(signature = (class, dex_file=None)))]
|
||||
pub fn remove_class(&mut self, class: &IdType, dex_file: Option<&str>) -> Result<()> {
|
||||
if let Some(dex_file) = dex_file {
|
||||
self.dex_files
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -12,80 +13,80 @@ use crate::{
|
|||
use androscalpel_serializer::consts::*;
|
||||
|
||||
/// Represent an apk
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
pub struct Class {
|
||||
/// Type, format described at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub descriptor: IdType,
|
||||
/// If the class is visible everywhere
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_public: bool,
|
||||
/// If the class is subclassable
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_final: bool,
|
||||
/// If the class is a 'multipy-implementable abstract class' AKA an interface
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_interface: bool,
|
||||
/// If the class is instanciable
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_abstract: bool,
|
||||
/// If the class is not directly defined in the source code
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_synthetic: bool,
|
||||
/// If the class is an annotation
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_annotation: bool,
|
||||
/// If the class is an enum
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_enum: bool,
|
||||
/// Name of the superclass, format described at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub superclass: Option<IdType>,
|
||||
/// List of the interfaces that class implement, format of the interfaces
|
||||
/// name is discribed at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub interfaces: Vec<IdType>,
|
||||
/// Name of the source file where this class is defined.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub source_file: Option<DexString>,
|
||||
|
||||
/// The static fields
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub static_fields: HashMap<IdField, Field>,
|
||||
/// The instance fields
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub instance_fields: HashMap<IdField, Field>,
|
||||
/// The direct (static, private or constructor) methods of the class
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub direct_methods: HashMap<IdMethod, Method>,
|
||||
/// The virtual (ie non direct) methods of the class
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub virtual_methods: HashMap<IdMethod, Method>,
|
||||
// Do we need to distinguish direct and virtual (all the other) methods?
|
||||
// Maybe overlapping descriptor (same name, class and proto?)
|
||||
/// The annotation related to this class (note: this does not include the
|
||||
/// methods/field/parameters annotations, they are stored in the methods and fields
|
||||
/// structutres)
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub annotations: Vec<DexAnnotationItem>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl Class {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(name: DexString) -> Result<Self> {
|
||||
Ok(Self {
|
||||
descriptor: IdType::new(name)?,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use anyhow::anyhow;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -16,26 +17,26 @@ use crate::{
|
|||
// type TmpHandlerType = (Vec<(IdType, u32)>, Option<u32>);
|
||||
|
||||
/// The code run by a method.
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct Code {
|
||||
// TODO: remove and compute this value from code?
|
||||
/// The number of registers used by the code
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub registers_size: u16,
|
||||
// TODO: what does it means? is it computable?
|
||||
/// The number of words of incoming arguments to the method
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub ins_size: u16,
|
||||
// TODO: what does it means? is it computable?
|
||||
/// The number of words of outgoing argument space
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub outs_size: u16,
|
||||
/// The names of the parameters if given
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub parameter_names: Option<Vec<Option<DexString>>>,
|
||||
/// The instructions.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub insns: Vec<Instruction>,
|
||||
}
|
||||
|
||||
|
|
@ -51,19 +52,19 @@ impl PartialEq for Code {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl Code {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[pyo3(signature = (registers_size, ins_size, outs_size, insns, parameter_names=None))]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
#[cfg_attr(feature = "python", pyo3(signature = (registers_size, ins_size, outs_size, insns, parameter_names=None)))]
|
||||
pub fn new(
|
||||
registers_size: u16,
|
||||
ins_size: u16,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use std::collections::HashSet;
|
|||
use std::hash::Hash;
|
||||
|
||||
use anyhow::{anyhow, bail, Context};
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{scalar::*, DexString, DexValue, Result, Visitable, VisitableMut, Visitor, VisitorMut};
|
||||
|
|
@ -13,7 +14,7 @@ use androscalpel_serializer::{StringDataItem, Uleb128};
|
|||
|
||||
/// The type of a method. The shorty is formated as described in
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||
#[pyclass(eq, ord, hash, frozen)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, ord, hash, frozen))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct IdMethodType {
|
||||
/// Type formated as described by <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||
|
|
@ -62,18 +63,18 @@ impl PartialOrd for IdMethodType {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl IdMethodType {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(return_type: IdType, parameters: Vec<IdType>) -> Self {
|
||||
Self {
|
||||
shorty: Self::compute_shorty(&return_type, ¶meters),
|
||||
|
|
@ -100,7 +101,7 @@ impl IdMethodType {
|
|||
/// )
|
||||
/// );
|
||||
/// ```
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_smali(smali_repr: &str) -> Result<Self> {
|
||||
if smali_repr.len() < 2 {
|
||||
bail!("'{smali_repr}' is to short to be a prototype");
|
||||
|
|
@ -229,7 +230,7 @@ impl IdMethodType {
|
|||
/// as described here <https://source.android.com/docs/core/runtime/dex-format#typedescriptor>
|
||||
// Not a clean rust enum because we want to be compatible with python, and maybe support strange
|
||||
// malware edge case?
|
||||
#[pyclass(eq, ord, hash, frozen)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, ord, hash, frozen))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct IdType(pub(crate) DexString);
|
||||
|
||||
|
|
@ -244,20 +245,24 @@ impl<V: VisitorMut> VisitableMut<V> for IdType {
|
|||
Ok(Self(v.visit_string(self.0)?))
|
||||
}
|
||||
}
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl IdType {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(
|
||||
#[pyo3(from_py_with = "crate::dex_string::as_dex_string")] ty: DexString,
|
||||
#[cfg_attr(
|
||||
feature = "python",
|
||||
pyo3(from_py_with = "crate::dex_string::as_dex_string")
|
||||
)]
|
||||
ty: DexString,
|
||||
) -> Result<Self> {
|
||||
// TODO: check format
|
||||
let ty = Self(ty);
|
||||
|
|
@ -266,7 +271,7 @@ impl IdType {
|
|||
}
|
||||
|
||||
/// Return a type from its string representation without checking its format
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn unchecked_new(ty: DexString) -> Self {
|
||||
Self(ty)
|
||||
}
|
||||
|
|
@ -288,7 +293,7 @@ impl IdType {
|
|||
/// IdType::class("androidx/core/util/Predicate")
|
||||
/// );
|
||||
/// ```
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_smali(smali_repr: &str) -> Result<Self> {
|
||||
Self::new(smali_repr.into())
|
||||
}
|
||||
|
|
@ -310,7 +315,7 @@ impl IdType {
|
|||
/// IdType::boolean(),
|
||||
/// ])
|
||||
/// ```
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn get_list_from_str(type_list: &str) -> Result<Vec<Self>> {
|
||||
let mut lst = vec![];
|
||||
let mut chars = type_list.chars();
|
||||
|
|
@ -364,66 +369,66 @@ impl IdType {
|
|||
}
|
||||
|
||||
/// Return the void type (for return type)
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn void() -> Self {
|
||||
Self("V".into())
|
||||
}
|
||||
|
||||
/// Return the boolean type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn boolean() -> Self {
|
||||
Self("Z".into())
|
||||
}
|
||||
/// Return the byte type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn byte() -> Self {
|
||||
Self("B".into())
|
||||
}
|
||||
|
||||
/// Return the short type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn short() -> Self {
|
||||
Self("S".into())
|
||||
}
|
||||
|
||||
/// Return the char type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn char() -> Self {
|
||||
Self("C".into())
|
||||
}
|
||||
|
||||
/// Return the int type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn int() -> Self {
|
||||
Self("I".into())
|
||||
}
|
||||
|
||||
/// Return the long type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn long() -> Self {
|
||||
Self("J".into())
|
||||
}
|
||||
|
||||
/// Return the float type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn float() -> Self {
|
||||
Self("F".into())
|
||||
}
|
||||
|
||||
/// Return the double type
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn double() -> Self {
|
||||
Self("D".into())
|
||||
}
|
||||
|
||||
/// Return the type for the class of fully qualified name `name`
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn class(name: &str) -> Self {
|
||||
Self(format!("L{name};").into())
|
||||
}
|
||||
|
||||
/// Return the type for an array of the specify `type_`
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn array(type_: &IdType) -> Self {
|
||||
let mut ty = type_.clone();
|
||||
ty.0 .0.utf16_size.0 += 1;
|
||||
|
|
@ -636,18 +641,18 @@ impl SmaliName for IdType {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq, ord, hash, frozen)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, ord, hash, frozen))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct IdField {
|
||||
/// The name of the field, format described at
|
||||
/// <https://source.android.com/docs/core/runtime/dex-format#membername>
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub name: DexString,
|
||||
/// The type of the field.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub type_: IdType,
|
||||
/// The class that own the field.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub class_: IdType,
|
||||
}
|
||||
|
||||
|
|
@ -669,20 +674,24 @@ impl<V: VisitorMut> VisitableMut<V> for IdField {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl IdField {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(
|
||||
#[pyo3(from_py_with = "crate::dex_string::as_dex_string")] name: DexString,
|
||||
#[cfg_attr(
|
||||
feature = "python",
|
||||
pyo3(from_py_with = "crate::dex_string::as_dex_string")
|
||||
)]
|
||||
name: DexString,
|
||||
type_: IdType,
|
||||
class_: IdType,
|
||||
) -> Self {
|
||||
|
|
@ -709,7 +718,7 @@ impl IdField {
|
|||
/// )
|
||||
/// );
|
||||
/// ```
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_smali(smali_repr: &str) -> Result<Self> {
|
||||
let arrow_i = smali_repr.find("->");
|
||||
if arrow_i.is_none() {
|
||||
|
|
@ -803,17 +812,17 @@ impl SmaliName for IdField {
|
|||
}
|
||||
|
||||
/// The Id of a method.
|
||||
#[pyclass(eq, ord, hash, frozen)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, ord, hash, frozen))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct IdMethod {
|
||||
/// The class containing the method.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub class_: IdType,
|
||||
/// The prototype (aka type or signature) of the method.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub proto: IdMethodType,
|
||||
/// The name of the method.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub name: DexString,
|
||||
}
|
||||
|
||||
|
|
@ -835,20 +844,24 @@ impl<V: VisitorMut> VisitableMut<V> for IdMethod {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl IdMethod {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(
|
||||
#[pyo3(from_py_with = "crate::dex_string::as_dex_string")] name: DexString,
|
||||
#[cfg_attr(
|
||||
feature = "python",
|
||||
pyo3(from_py_with = "crate::dex_string::as_dex_string")
|
||||
)]
|
||||
name: DexString,
|
||||
proto: IdMethodType,
|
||||
class_: IdType,
|
||||
) -> Self {
|
||||
|
|
@ -884,7 +897,7 @@ impl IdMethod {
|
|||
/// )
|
||||
/// );
|
||||
/// ```
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_smali(smali_repr: &str) -> Result<Self> {
|
||||
let arrow_i = smali_repr.find("->");
|
||||
if arrow_i.is_none() {
|
||||
|
|
@ -998,7 +1011,7 @@ impl SmaliName for IdMethod {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq, ord, hash, frozen)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, ord, hash, frozen))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
||||
pub struct IdEnum(pub IdField);
|
||||
|
||||
|
|
@ -1014,18 +1027,18 @@ impl<V: VisitorMut> VisitableMut<V> for IdEnum {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl IdEnum {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: IdField) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use crate::{Result, Visitable, VisitableMut, Visitor, VisitorMut};
|
||||
use pyo3::exceptions::PyTypeError;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::cmp::{Ord, PartialOrd};
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::{exceptions::PyTypeError, prelude::*};
|
||||
|
||||
#[pyclass(eq, ord, frozen, hash)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, ord, frozen, hash))]
|
||||
#[derive(Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub struct DexString(pub androscalpel_serializer::StringDataItem);
|
||||
|
||||
|
|
@ -149,6 +149,7 @@ impl Hash for DexString {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
pub fn as_dex_string(obj: &Bound<'_, PyAny>) -> PyResult<DexString> {
|
||||
if let Ok(string) = DexString::extract_bound(obj) {
|
||||
Ok(string)
|
||||
|
|
@ -162,18 +163,18 @@ pub fn as_dex_string(obj: &Bound<'_, PyAny>) -> PyResult<DexString> {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexString {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(s: &str) -> Self {
|
||||
s.into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -12,45 +13,45 @@ use crate::{
|
|||
use androscalpel_serializer::consts::*;
|
||||
|
||||
/// Represent a field.
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct Field {
|
||||
/// The structure used to reference this field.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub descriptor: IdField,
|
||||
/// The field visibility
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub visibility: FieldVisibility,
|
||||
/// If the field is defined for the class globally
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_static: bool,
|
||||
/// If the field is immutable after construction
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_final: bool,
|
||||
/// For thread safety
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_volatile: bool,
|
||||
/// If the field should **not** be saved by default serialization
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_transient: bool,
|
||||
/// If the field is not defined in the source code
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_synthetic: bool,
|
||||
/// If the field is an enumerated value
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_enum: bool,
|
||||
/// The default value of this field
|
||||
pub value: Option<DexValue>,
|
||||
/// The annotations for this field
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub annotations: Vec<DexAnnotationItem>,
|
||||
/// Hidden Api data.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub hiddenapi: Option<HiddenApiData>,
|
||||
}
|
||||
|
||||
/// Represent the visibility of a field
|
||||
#[pyclass(eq, eq_int)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, eq_int))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum FieldVisibility {
|
||||
Public,
|
||||
|
|
@ -59,18 +60,18 @@ pub enum FieldVisibility {
|
|||
None_, // Actually quite common
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl Field {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(descriptor: IdField) -> Self {
|
||||
Self {
|
||||
descriptor,
|
||||
|
|
@ -124,12 +125,14 @@ impl Field {
|
|||
}
|
||||
|
||||
/// Return the value as a python object
|
||||
#[cfg(feature = "python")]
|
||||
#[getter]
|
||||
pub fn get_value(&self) -> Option<DexValue> {
|
||||
self.value.clone()
|
||||
}
|
||||
|
||||
/// Set the value from a python object
|
||||
#[cfg(feature = "python")]
|
||||
#[setter]
|
||||
pub fn set_value(&mut self, ob: &Bound<'_, PyAny>) -> PyResult<()> {
|
||||
self.value = Some(ob.extract()?);
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
use crate::{Result, Visitable, VisitableMut, Visitor, VisitorMut};
|
||||
use log::warn;
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[pyclass]
|
||||
#[cfg_attr(feature = "python", pyclass)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
|
||||
pub struct HiddenApiData {
|
||||
pub permission: HiddenApiPermission,
|
||||
|
|
@ -56,7 +57,7 @@ impl<V: VisitorMut> VisitableMut<V> for HiddenApiData {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[cfg_attr(feature = "python", pyclass)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
|
||||
pub enum HiddenApiPermission {
|
||||
/// Interfaces that can be freely used and are supported as
|
||||
|
|
@ -147,7 +148,7 @@ impl From<HiddenApiPermission> for androscalpel_serializer::HiddenApiValue {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[cfg_attr(feature = "python", pyclass)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
|
||||
pub struct HiddenApiDomain {
|
||||
pub is_core_platform_api: bool,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use androscalpel_serializer::Instruction as InsFormat;
|
|||
use androscalpel_serializer::Serializable;
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
|
@ -31,7 +32,7 @@ const I32_MIN_AS_I64: i64 = i32::MIN as i64;
|
|||
const I32_MAX_AS_I64: i64 = i32::MAX as i64;
|
||||
const U16_MAX_AS_USIZE: usize = u16::MAX as usize;
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub enum Instruction {
|
||||
/// Waste a cycle.
|
||||
|
|
@ -2094,13 +2095,13 @@ macro_rules! raw_ins_invoke {
|
|||
}};
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl Instruction {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
|
@ -6596,31 +6597,31 @@ impl Instruction {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct CallSite {
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub method_handle: MethodHandle,
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub name: DexString,
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub type_: IdMethodType,
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub args: Vec<DexValue>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl CallSite {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(
|
||||
method_handle: MethodHandle,
|
||||
name: DexString,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// python, TryInto should be prefered
|
||||
use anyhow::Result;
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
pub mod annotation;
|
||||
|
|
@ -18,6 +19,7 @@ pub mod hiddenapi;
|
|||
pub mod instructions;
|
||||
pub mod method;
|
||||
pub mod method_handle;
|
||||
#[cfg(feature = "python")]
|
||||
pub mod py_utils;
|
||||
pub mod scalar;
|
||||
pub mod value;
|
||||
|
|
@ -44,6 +46,7 @@ pub use visitor::*;
|
|||
mod tests;
|
||||
|
||||
/// Androscalpel.
|
||||
#[cfg(feature = "python")]
|
||||
#[pymodule]
|
||||
fn androscalpel(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
pyo3_log::init();
|
||||
|
|
@ -90,6 +93,7 @@ fn androscalpel(py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|||
}
|
||||
|
||||
/// Dalvik opcode for Androscalpel.
|
||||
#[cfg(feature = "python")]
|
||||
fn androscalpel_ins(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
m.add_class::<ins::CallSite>()?;
|
||||
m.add_class::<ins::Instruction>()?;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -12,67 +13,67 @@ use crate::{
|
|||
use androscalpel_serializer::consts::*;
|
||||
|
||||
/// Represent a method.
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||
pub struct Method {
|
||||
/// The structure used to reference this method.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub descriptor: IdMethod,
|
||||
/// The field visibility.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub visibility: MethodVisibility,
|
||||
/// Static methods do not take this in argument.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_static: bool,
|
||||
/// Final methods are not averridable.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_final: bool,
|
||||
/// Synchronized method automatically acquire their associated lock around call.
|
||||
/// Can only be set in native method, (`[Self::is_native] = true`).
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_synchronized: bool,
|
||||
/// Bridge are automatically added by the compiler as a type-safe bridge.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_bridge: bool,
|
||||
/// If the last argument should be treated as a "rest" argument by compiler
|
||||
/// (for method of variable number of argument).
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_varargs: bool,
|
||||
/// If the method is a native method.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_native: bool,
|
||||
/// Abstract methods are not implemented by the class.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_abstract: bool,
|
||||
/// If the method must use strict rules for floating point arithmetic.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_strictfp: bool,
|
||||
/// Synthetic method are not directly defined in the source code.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_synthetic: bool,
|
||||
/// If the method is a constructor.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_constructor: bool,
|
||||
/// If the method is declared as synchronize (just indicatif)
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub is_declared_syncrhonized: bool,
|
||||
/// The annotations for this method
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub annotations: Vec<DexAnnotationItem>,
|
||||
/// The annotations for the parameters of this method method
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub parameters_annotations: Vec<Vec<DexAnnotationItem>>,
|
||||
/// Hidden Api data.
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub hiddenapi: Option<HiddenApiData>,
|
||||
|
||||
/// The code of the method
|
||||
#[pyo3(get)]
|
||||
#[cfg_attr(feature = "python", pyo3(get))]
|
||||
pub code: Option<Code>,
|
||||
}
|
||||
|
||||
/// Represent the visibility of a field
|
||||
#[pyclass(eq, eq_int)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq, eq_int))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub enum MethodVisibility {
|
||||
Public,
|
||||
|
|
@ -81,18 +82,18 @@ pub enum MethodVisibility {
|
|||
None_, // Actually quite common
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl Method {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(descriptor: IdMethod) -> Self {
|
||||
// TODO: take code option as arg and set the default flags accordingly
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
use crate::dex_id::*;
|
||||
|
|
@ -13,7 +14,7 @@ use crate::{
|
|||
};
|
||||
|
||||
/// The structure use to reference a method invocation.
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||
pub enum MethodHandle {
|
||||
StaticPut { field: IdField },
|
||||
|
|
@ -78,13 +79,13 @@ impl<V: VisitorMut> VisitableMut<V> for MethodHandle {
|
|||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl MethodHandle {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,23 +8,25 @@ use crate::{
|
|||
DexString, DexValue, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Visitable,
|
||||
VisitableMut, Visitor, VisitorMut,
|
||||
};
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::prelude::*;
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexByte(pub i8);
|
||||
#[pymethods]
|
||||
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexByte {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: i8) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -42,21 +44,21 @@ impl DexByte {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexShort(pub i16);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexShort {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: i16) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -74,21 +76,21 @@ impl DexShort {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexChar(pub u16);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexChar {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: u16) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -106,21 +108,21 @@ impl DexChar {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexInt(pub i32);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexInt {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: i32) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -138,21 +140,21 @@ impl DexInt {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexLong(pub i64);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexLong {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: i64) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -170,21 +172,21 @@ impl DexLong {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
|
||||
pub struct DexFloat(pub f32);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexFloat {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: f32) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -202,21 +204,21 @@ impl DexFloat {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
|
||||
pub struct DexDouble(pub f64);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexDouble {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: f64) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -235,21 +237,21 @@ impl DexDouble {
|
|||
}
|
||||
|
||||
/* DexString is already define in lib.rs, TODO: move the version in lib.rs here
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DexString(pub u32);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexString {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: u32) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -268,21 +270,21 @@ impl DexString {
|
|||
}
|
||||
*/
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexNull;
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexNull {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn _new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
|
@ -296,21 +298,21 @@ impl DexNull {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
||||
pub struct DexBoolean(pub bool);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexBoolean {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn new(val: bool) -> Self {
|
||||
Self(val)
|
||||
}
|
||||
|
|
@ -328,21 +330,21 @@ impl DexBoolean {
|
|||
}
|
||||
}
|
||||
|
||||
#[pyclass(eq)]
|
||||
#[cfg_attr(feature = "python", pyclass(eq))]
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
|
||||
pub struct DexArray(pub Vec<DexValue>);
|
||||
#[pymethods]
|
||||
#[cfg_attr(feature = "python", pymethods)]
|
||||
impl DexArray {
|
||||
pub fn to_json(&self) -> Result<String> {
|
||||
Ok(serde_json::to_string(self)?)
|
||||
}
|
||||
|
||||
#[staticmethod]
|
||||
#[cfg_attr(feature = "python", staticmethod)]
|
||||
pub fn from_json(json: &str) -> Result<Self> {
|
||||
Ok(serde_json::from_str(json)?)
|
||||
}
|
||||
|
||||
#[new]
|
||||
#[cfg_attr(feature = "python", new)]
|
||||
pub fn _new(arr: Vec<DexValue>) -> Self {
|
||||
Self(arr)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
|
||||
use pyo3::exceptions::PyTypeError;
|
||||
use pyo3::prelude::*;
|
||||
#[cfg(feature = "python")]
|
||||
use pyo3::{exceptions::PyTypeError, prelude::*};
|
||||
|
||||
use crate::{
|
||||
dex_id::*, scalar::*, DexAnnotation, DexString, MethodHandle, Result, Visitable, VisitableMut,
|
||||
|
|
@ -83,6 +83,7 @@ impl<V: VisitorMut> VisitableMut<V> for DexValue {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
impl<'source> FromPyObject<'source> for DexValue {
|
||||
fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
|
||||
if let Ok(val) = DexByte::extract_bound(ob) {
|
||||
|
|
@ -305,7 +306,7 @@ impl DexValue {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
impl<'py> IntoPyObject<'py> for DexValue {
|
||||
type Target = PyAny;
|
||||
type Output = Bound<'py, Self::Target>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue