diff --git a/androscalpel/src/annotation.rs b/androscalpel/src/annotation.rs index 1c4412b..68baed1 100644 --- a/androscalpel/src/annotation.rs +++ b/androscalpel/src/annotation.rs @@ -11,7 +11,7 @@ use crate::{ }; /// Annotation with a visibility -#[pyclass] +#[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 @@ -32,10 +32,6 @@ pub struct DexAnnotationItem { #[pymethods] impl DexAnnotationItem { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - #[new] pub fn new(annotation: DexAnnotation) -> Self { Self { @@ -126,7 +122,7 @@ impl VisitableMut for DexAnnotationItem { } /// An annotation. -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct DexAnnotation { // TODO: check the relation between type and encoded_value. @@ -142,10 +138,6 @@ pub struct DexAnnotation { #[pymethods] impl DexAnnotation { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - #[new] pub fn new(type_: IdType, elements: HashMap) -> Self { Self { type_, elements } diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index 7da2c16..e1bddbc 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -28,7 +28,7 @@ pub struct DexFile { } /// Represent an apk. -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Default, Deserialize, Serialize)] pub struct Apk { pub dex_files: HashMap, // TODO: use accessort for chache invalidation @@ -3087,10 +3087,6 @@ impl Apk { Ok(()) } - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - #[pyo3(name = "gen_raw_dex")] //Sad GIL noise pub fn py_gen_raw_dex(&self, py: Python<'_>) -> Result> { Ok(self diff --git a/androscalpel/src/class.rs b/androscalpel/src/class.rs index e5c2096..7a26c0a 100644 --- a/androscalpel/src/class.rs +++ b/androscalpel/src/class.rs @@ -12,7 +12,7 @@ use crate::{ use androscalpel_serializer::consts::*; /// Represent an apk -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] pub struct Class { /// Type, format described at @@ -382,10 +382,6 @@ impl Class { } flags } - - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } } impl Visitable for Class { diff --git a/androscalpel/src/code.rs b/androscalpel/src/code.rs index 2df1cfd..93dbee1 100644 --- a/androscalpel/src/code.rs +++ b/androscalpel/src/code.rs @@ -16,7 +16,7 @@ use crate::{ // type TmpHandlerType = (Vec<(IdType, u32)>, Option); /// The code run by a method. -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Code { // TODO: remove and compute this value from code? @@ -39,6 +39,7 @@ pub struct Code { pub insns: Vec, } +// TODO reimplement PartialEq: label should become address independant impl PartialEq for Code { fn eq(&self, other: &Self) -> bool { let comparable_self = self.semantic_comparable().unwrap(); @@ -50,8 +51,6 @@ impl PartialEq for Code { } } -// TODO reimplement PartialEq: label should become address independant - #[pymethods] impl Code { pub fn to_json(&self) -> Result { @@ -150,10 +149,6 @@ impl Code { handles } - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - /// Return all the labels used by instrutions in the code. pub fn get_referenced_label(&self) -> HashSet { let mut used_labels = HashSet::new(); diff --git a/androscalpel/src/dex_id.rs b/androscalpel/src/dex_id.rs index b49b6c0..a232df7 100644 --- a/androscalpel/src/dex_id.rs +++ b/androscalpel/src/dex_id.rs @@ -2,12 +2,10 @@ use serde::{Deserialize, Serialize}; use std::cmp::{Ord, Ordering, PartialOrd}; -use std::collections::hash_map::DefaultHasher; use std::collections::HashSet; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use anyhow::{anyhow, bail, Context}; -use pyo3::class::basic::CompareOp; use pyo3::prelude::*; use crate::{scalar::*, DexString, DexValue, Result, Visitable, VisitableMut, Visitor, VisitorMut}; @@ -15,7 +13,7 @@ use androscalpel_serializer::{StringDataItem, Uleb128}; /// The type of a method. The shorty is formated as described in /// -#[pyclass] +#[pyclass(eq, ord, hash, frozen)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdMethodType { /// Type formated as described by @@ -167,12 +165,6 @@ impl IdMethodType { self.parameters.clone() } - pub fn __hash__(&self) -> u64 { - let mut hasher = DefaultHasher::new(); - self.hash(&mut hasher); - hasher.finish() - } - /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); @@ -198,10 +190,6 @@ impl IdMethodType { protos.insert(self.clone()); protos } - - fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { - op.matches(self.cmp(other)) - } } impl SmaliName for IdMethodType { @@ -241,7 +229,7 @@ impl IdMethodType { /// as described here // Not a clean rust enum because we want to be compatible with python, and maybe support strange // malware edge case? -#[pyclass] +#[pyclass(eq, ord, hash, frozen)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct IdType(pub(crate) DexString); @@ -620,12 +608,6 @@ impl IdType { } } - pub fn __hash__(&self) -> u64 { - let mut hasher = DefaultHasher::new(); - self.hash(&mut hasher); - hasher.finish() - } - /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); @@ -639,10 +621,6 @@ impl IdType { types.insert(self.clone()); types } - - fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { - op.matches(self.cmp(other)) - } // TODO: TESTS } @@ -658,7 +636,7 @@ impl SmaliName for IdType { } } -#[pyclass] +#[pyclass(eq, ord, hash, frozen)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdField { /// The name of the field, format described at @@ -770,12 +748,6 @@ impl IdField { format!("IdField(\"{name}\", {ty}, {class})") } - pub fn __hash__(&self) -> u64 { - let mut hasher = DefaultHasher::new(); - self.hash(&mut hasher); - hasher.finish() - } - /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); @@ -799,10 +771,6 @@ impl IdField { fields.insert(self.clone()); fields } - - fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { - op.matches(self.cmp(other)) - } } impl Ord for IdField { @@ -835,7 +803,7 @@ impl SmaliName for IdField { } /// The Id of a method. -#[pyclass] +#[pyclass(eq, ord, hash, frozen)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct IdMethod { /// The class containing the method. @@ -966,12 +934,6 @@ impl IdMethod { ) } - pub fn __hash__(&self) -> u64 { - let mut hasher = DefaultHasher::new(); - self.hash(&mut hasher); - hasher.finish() - } - /// Return all strings referenced in the Id. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); @@ -1002,10 +964,6 @@ impl IdMethod { method_ids.insert(self.clone()); method_ids } - - fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { - op.matches(self.cmp(other)) - } } impl Ord for IdMethod { @@ -1040,8 +998,8 @@ impl SmaliName for IdMethod { } } -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)] +#[pyclass(eq, ord, hash, frozen)] +#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] pub struct IdEnum(pub IdField); impl Visitable for IdEnum { @@ -1098,10 +1056,6 @@ impl IdEnum { pub fn get_all_field_ids(&self) -> HashSet { self.0.get_all_field_ids() } - - fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { - op.matches(self.cmp(other)) - } } // Not to sure about this one diff --git a/androscalpel/src/dex_string.rs b/androscalpel/src/dex_string.rs index b9f0016..080a2aa 100644 --- a/androscalpel/src/dex_string.rs +++ b/androscalpel/src/dex_string.rs @@ -1,15 +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::hash_map::DefaultHasher; use std::collections::HashSet; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; -use pyo3::class::basic::CompareOp; -use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; -#[pyclass] +#[pyclass(eq, ord, frozen, hash)] #[derive(Clone, PartialEq, Eq, Ord, PartialOrd)] pub struct DexString(pub androscalpel_serializer::StringDataItem); @@ -198,23 +196,10 @@ impl DexString { self.into() } - fn __hash__(&self) -> u64 { - let mut hasher = DefaultHasher::new(); - self.hash(&mut hasher); - hasher.finish() - } - /// Return all strings references in the value. pub fn get_all_strings(&self) -> HashSet { let mut strings = HashSet::new(); strings.insert(self.clone()); strings } - - fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> PyResult { - let other: Self = other - .extract() - .or(::extract_bound(other).map(|string| string.into()))?; - Ok(op.matches(self.0.cmp(&other.0))) - } } diff --git a/androscalpel/src/field.rs b/androscalpel/src/field.rs index c887089..1bc4962 100644 --- a/androscalpel/src/field.rs +++ b/androscalpel/src/field.rs @@ -12,7 +12,7 @@ use crate::{ use androscalpel_serializer::consts::*; /// Represent a field. -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct Field { /// The structure used to reference this field. @@ -252,10 +252,6 @@ impl Field { pub fn has_annotations(&self) -> bool { !self.annotations.is_empty() } - - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } } impl Visitable for Field { diff --git a/androscalpel/src/instructions.rs b/androscalpel/src/instructions.rs index d1743f1..bcebdc3 100644 --- a/androscalpel/src/instructions.rs +++ b/androscalpel/src/instructions.rs @@ -31,9 +31,8 @@ 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; -// TODO: impl Eq for call site to derive here? +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -#[pyclass] pub enum Instruction { /// Waste a cycle. Nop {}, @@ -2097,10 +2096,6 @@ macro_rules! raw_ins_invoke { #[pymethods] impl Instruction { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - pub fn to_json(&self) -> Result { Ok(serde_json::to_string(self)?) } @@ -6601,7 +6596,7 @@ impl Instruction { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct CallSite { #[pyo3(get)] @@ -6616,10 +6611,6 @@ pub struct CallSite { #[pymethods] impl CallSite { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - pub fn to_json(&self) -> Result { Ok(serde_json::to_string(self)?) } diff --git a/androscalpel/src/method.rs b/androscalpel/src/method.rs index b95c0e6..fd55307 100644 --- a/androscalpel/src/method.rs +++ b/androscalpel/src/method.rs @@ -12,7 +12,7 @@ use crate::{ use androscalpel_serializer::consts::*; /// Represent a method. -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] pub struct Method { /// The structure used to reference this method. @@ -293,10 +293,6 @@ impl Method { .iter() .any(|list| !list.is_empty()) } - - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } } impl Visitable for Method { diff --git a/androscalpel/src/method_handle.rs b/androscalpel/src/method_handle.rs index 12ca574..e2ed216 100644 --- a/androscalpel/src/method_handle.rs +++ b/androscalpel/src/method_handle.rs @@ -13,8 +13,8 @@ use crate::{ }; /// The structure use to reference a method invocation. +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] -#[pyclass] pub enum MethodHandle { StaticPut { field: IdField }, StaticGet { field: IdField }, diff --git a/androscalpel/src/scalar.rs b/androscalpel/src/scalar.rs index 4db05da..849c24a 100644 --- a/androscalpel/src/scalar.rs +++ b/androscalpel/src/scalar.rs @@ -10,7 +10,7 @@ use crate::{ }; use pyo3::prelude::*; -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexByte(pub i8); #[pymethods] @@ -42,7 +42,7 @@ impl DexByte { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexShort(pub i16); #[pymethods] @@ -74,7 +74,7 @@ impl DexShort { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexChar(pub u16); #[pymethods] @@ -106,7 +106,7 @@ impl DexChar { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexInt(pub i32); #[pymethods] @@ -138,7 +138,7 @@ impl DexInt { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexLong(pub i64); #[pymethods] @@ -170,7 +170,7 @@ impl DexLong { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)] pub struct DexFloat(pub f32); #[pymethods] @@ -202,7 +202,7 @@ impl DexFloat { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)] pub struct DexDouble(pub f64); #[pymethods] @@ -235,7 +235,7 @@ impl DexDouble { } /* DexString is already define in lib.rs, TODO: move the version in lib.rs here -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct DexString(pub u32); #[pymethods] @@ -268,7 +268,7 @@ impl DexString { } */ -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexNull; #[pymethods] @@ -296,7 +296,7 @@ impl DexNull { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] pub struct DexBoolean(pub bool); #[pymethods] @@ -328,7 +328,7 @@ impl DexBoolean { } } -#[pyclass] +#[pyclass(eq)] #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct DexArray(pub Vec); #[pymethods]