add methods
This commit is contained in:
parent
0a112802cd
commit
b704e7cbad
4 changed files with 300 additions and 73 deletions
|
|
@ -88,11 +88,18 @@ impl Apk {
|
||||||
}
|
}
|
||||||
let mut static_fields = vec![];
|
let mut static_fields = vec![];
|
||||||
let mut instance_fields = vec![];
|
let mut instance_fields = vec![];
|
||||||
|
let mut direct_methods = vec![];
|
||||||
|
let mut virtual_methods = vec![];
|
||||||
let data_off = class_item.class_data_off;
|
let data_off = class_item.class_data_off;
|
||||||
if data_off != 0 {
|
if data_off != 0 {
|
||||||
let data = dex.get_struct_at_offset::<ClassDataItem>(data_off)?;
|
let data = dex.get_struct_at_offset::<ClassDataItem>(data_off)?;
|
||||||
static_fields = Self::get_field_list_from_dex(&data.static_fields, dex)?;
|
static_fields = Self::get_field_list_from_encoded_field_list(&data.static_fields, dex)?;
|
||||||
instance_fields = Self::get_field_list_from_dex(&data.instance_fields, dex)?;
|
instance_fields =
|
||||||
|
Self::get_field_list_from_encoded_field_list(&data.instance_fields, dex)?;
|
||||||
|
direct_methods =
|
||||||
|
Self::get_method_list_from_encoded_field_list(&data.direct_methods, dex)?;
|
||||||
|
virtual_methods =
|
||||||
|
Self::get_method_list_from_encoded_field_list(&data.virtual_methods, dex)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if class_item.static_values_off != 0 {
|
if class_item.static_values_off != 0 {
|
||||||
|
|
@ -130,6 +137,8 @@ impl Apk {
|
||||||
is_enum,
|
is_enum,
|
||||||
instance_fields,
|
instance_fields,
|
||||||
static_fields,
|
static_fields,
|
||||||
|
direct_methods,
|
||||||
|
virtual_methods,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -284,51 +293,67 @@ impl Apk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_field_list_from_dex(
|
/// Return a [`Field`] from it's idx (index in `field_ids`) in the dex file and its access flags
|
||||||
encoded_fields: &[EncodedField],
|
/// ([`EncodedField.access_flags`])
|
||||||
|
pub fn get_field_from_idx(
|
||||||
|
idx: usize,
|
||||||
|
Uleb128(access_flags): Uleb128,
|
||||||
dex: &DexFileReader,
|
dex: &DexFileReader,
|
||||||
) -> Result<Vec<Field>> {
|
) -> Result<Field> {
|
||||||
let mut idx = 0;
|
let descriptor = Self::get_id_field_from_idx(idx, dex)?;
|
||||||
let mut fields = vec![];
|
|
||||||
for field in encoded_fields {
|
|
||||||
idx += field.field_idx_diff.0;
|
|
||||||
|
|
||||||
let id_item = dex.get_field_id(idx as usize)?;
|
let is_public = (access_flags & ACC_PUBLIC) != 0;
|
||||||
let class_ty = dex.get_type_id(id_item.class_idx as usize)?;
|
let is_private = (access_flags & ACC_PRIVATE) != 0;
|
||||||
let class: DexString = dex.get_string(class_ty.descriptor_idx)?.into();
|
let is_protected = (access_flags & ACC_PROTECTED) != 0;
|
||||||
let ty = dex.get_type_id(id_item.type_idx as usize)?;
|
let is_static = (access_flags & ACC_STATIC) != 0;
|
||||||
let ty = dex.get_string(ty.descriptor_idx)?.into();
|
let is_final = (access_flags & ACC_FINAL) != 0;
|
||||||
let name: DexString = dex.get_string(id_item.name_idx)?.into();
|
let is_volatile = (access_flags & ACC_VOLATILE) != 0;
|
||||||
|
let is_transient = (access_flags & ACC_TRANSIENT) != 0;
|
||||||
let is_public = (field.access_flags.0 & ACC_PUBLIC) != 0;
|
let is_synthetic = (access_flags & ACC_SYNTHETIC) != 0;
|
||||||
let is_private = (field.access_flags.0 & ACC_PRIVATE) != 0;
|
let is_enum = (access_flags & ACC_ENUM) != 0;
|
||||||
let is_protected = (field.access_flags.0 & ACC_PROTECTED) != 0;
|
|
||||||
let is_static = (field.access_flags.0 & ACC_STATIC) != 0;
|
|
||||||
let is_final = (field.access_flags.0 & ACC_FINAL) != 0;
|
|
||||||
let is_volatile = (field.access_flags.0 & ACC_VOLATILE) != 0;
|
|
||||||
let is_transient = (field.access_flags.0 & ACC_TRANSIENT) != 0;
|
|
||||||
let is_synthetic = (field.access_flags.0 & ACC_SYNTHETIC) != 0;
|
|
||||||
let is_enum = (field.access_flags.0 & ACC_ENUM) != 0;
|
|
||||||
let visibility = match (is_public, is_private, is_protected) {
|
let visibility = match (is_public, is_private, is_protected) {
|
||||||
(true, false, false) => FieldVisibility::Public,
|
(true, false, false) => FieldVisibility::Public,
|
||||||
(false, true, false) => FieldVisibility::Private,
|
(false, true, false) => FieldVisibility::Private,
|
||||||
(false, false, true) => FieldVisibility::Protected,
|
(false, false, true) => FieldVisibility::Protected,
|
||||||
(false, false, false) => FieldVisibility::None_,
|
(false, false, false) => FieldVisibility::None_,
|
||||||
(pbl, prv, prt) => {
|
(pbl, prv, prt) => {
|
||||||
let class: String = class.into();
|
let class: String = descriptor.class_.0.into();
|
||||||
let name: String = name.into();
|
let name: String = descriptor.name.into();
|
||||||
return Err(Error::InconsistantStruct(format!(
|
return Err(Error::InconsistantStruct(format!(
|
||||||
"Inconsistant visiblity found in {class}.{name}: \
|
"Inconsistant visiblity found in {class}.{name}: \
|
||||||
(public: {pbl}, private: {prv}, protected: {prt})"
|
(public: {pbl}, private: {prv}, protected: {prt})"
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let descriptor = IdField {
|
if access_flags
|
||||||
name,
|
& !(ACC_PUBLIC
|
||||||
type_: IdType(ty),
|
| ACC_PRIVATE
|
||||||
class_: IdType(class),
|
| ACC_PROTECTED
|
||||||
};
|
| ACC_STATIC
|
||||||
fields.push(Field {
|
| ACC_FINAL
|
||||||
|
| ACC_VOLATILE
|
||||||
|
| ACC_TRANSIENT
|
||||||
|
| ACC_SYNTHETIC
|
||||||
|
| ACC_ENUM)
|
||||||
|
!= 0
|
||||||
|
{
|
||||||
|
info!(
|
||||||
|
"Unexpected flags found in {} for : 0x{:x} (unknown flags: 0x{:x})",
|
||||||
|
descriptor.__repr__(),
|
||||||
|
access_flags,
|
||||||
|
access_flags
|
||||||
|
& !(ACC_PUBLIC
|
||||||
|
| ACC_PRIVATE
|
||||||
|
| ACC_PROTECTED
|
||||||
|
| ACC_STATIC
|
||||||
|
| ACC_FINAL
|
||||||
|
| ACC_VOLATILE
|
||||||
|
| ACC_TRANSIENT
|
||||||
|
| ACC_SYNTHETIC
|
||||||
|
| ACC_ENUM)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(Field {
|
||||||
descriptor,
|
descriptor,
|
||||||
visibility,
|
visibility,
|
||||||
is_static,
|
is_static,
|
||||||
|
|
@ -340,8 +365,152 @@ impl Apk {
|
||||||
value: None,
|
value: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a list of field from a list of [`EncodedField`].
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// The index of the fields is computed by summing the [`EncodedField.field_idx_diff`] of the
|
||||||
|
/// previous element of the list the diff of the current field, so the list must be preserved
|
||||||
|
/// as in the dex file.
|
||||||
|
pub fn get_field_list_from_encoded_field_list(
|
||||||
|
encoded_fields: &[EncodedField],
|
||||||
|
dex: &DexFileReader,
|
||||||
|
) -> Result<Vec<Field>> {
|
||||||
|
let mut idx = 0;
|
||||||
|
let mut fields = vec![];
|
||||||
|
for field in encoded_fields {
|
||||||
|
idx += field.field_idx_diff.0;
|
||||||
|
|
||||||
|
fields.push(Self::get_field_from_idx(
|
||||||
|
idx as usize,
|
||||||
|
field.access_flags,
|
||||||
|
dex,
|
||||||
|
)?);
|
||||||
|
}
|
||||||
Ok(fields)
|
Ok(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a [`Method`] from it's idx (index in `method_ids`) in the dex file and its access flags
|
||||||
|
/// ([`EncodedMethod.access_flags`]) and code offset ([`EncodedMethod.code_off`]).
|
||||||
|
pub fn get_method_from_idx(
|
||||||
|
idx: usize,
|
||||||
|
Uleb128(access_flags): Uleb128,
|
||||||
|
Uleb128(_code_off): Uleb128,
|
||||||
|
dex: &DexFileReader,
|
||||||
|
) -> Result<Method> {
|
||||||
|
let descriptor = Self::get_id_method_from_idx(idx, dex)?;
|
||||||
|
|
||||||
|
let is_public = (access_flags & ACC_PUBLIC) != 0;
|
||||||
|
let is_private = (access_flags & ACC_PRIVATE) != 0;
|
||||||
|
let is_protected = (access_flags & ACC_PROTECTED) != 0;
|
||||||
|
let is_static = (access_flags & ACC_STATIC) != 0;
|
||||||
|
let is_final = (access_flags & ACC_FINAL) != 0;
|
||||||
|
let is_synchronized = (access_flags & ACC_SYNCHRONIZED) != 0;
|
||||||
|
let is_bridge = (access_flags & ACC_BRIDGE) != 0;
|
||||||
|
let is_varargs = (access_flags & ACC_VARARGS) != 0;
|
||||||
|
let is_native = (access_flags & ACC_NATIVE) != 0;
|
||||||
|
let is_abstract = (access_flags & ACC_ABSTRACT) != 0;
|
||||||
|
let is_strictfp = (access_flags & ACC_STRICT) != 0;
|
||||||
|
let is_synthetic = (access_flags & ACC_SYNTHETIC) != 0;
|
||||||
|
let is_constructor = (access_flags & ACC_CONSTRUCTOR) != 0;
|
||||||
|
let is_declared_syncrhonized = (access_flags & ACC_DECLARED_SYNCHRONIZED) != 0;
|
||||||
|
let visibility = match (is_public, is_private, is_protected) {
|
||||||
|
(true, false, false) => MethodVisibility::Public,
|
||||||
|
(false, true, false) => MethodVisibility::Private,
|
||||||
|
(false, false, true) => MethodVisibility::Protected,
|
||||||
|
(false, false, false) => MethodVisibility::None_,
|
||||||
|
(pbl, prv, prt) => {
|
||||||
|
return Err(Error::InconsistantStruct(format!(
|
||||||
|
"Inconsistant visiblity found in {}: \
|
||||||
|
(public: {pbl}, private: {prv}, protected: {prt})",
|
||||||
|
descriptor.__repr__()
|
||||||
|
)));
|
||||||
|
// TODO: replace by public?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if access_flags
|
||||||
|
& !(ACC_PUBLIC
|
||||||
|
| ACC_PRIVATE
|
||||||
|
| ACC_PROTECTED
|
||||||
|
| ACC_STATIC
|
||||||
|
| ACC_FINAL
|
||||||
|
| ACC_SYNCHRONIZED
|
||||||
|
| ACC_BRIDGE
|
||||||
|
| ACC_VARARGS
|
||||||
|
| ACC_NATIVE
|
||||||
|
| ACC_ABSTRACT
|
||||||
|
| ACC_STRICT
|
||||||
|
| ACC_SYNTHETIC
|
||||||
|
| ACC_CONSTRUCTOR
|
||||||
|
| ACC_DECLARED_SYNCHRONIZED)
|
||||||
|
!= 0
|
||||||
|
{
|
||||||
|
info!(
|
||||||
|
"Unexpected flags found in {} for : 0x{:x} (unknown flags: 0x{:x})",
|
||||||
|
descriptor.__repr__(),
|
||||||
|
access_flags,
|
||||||
|
access_flags
|
||||||
|
& !(ACC_PUBLIC
|
||||||
|
| ACC_PRIVATE
|
||||||
|
| ACC_PROTECTED
|
||||||
|
| ACC_STATIC
|
||||||
|
| ACC_FINAL
|
||||||
|
| ACC_SYNCHRONIZED
|
||||||
|
| ACC_BRIDGE
|
||||||
|
| ACC_VARARGS
|
||||||
|
| ACC_NATIVE
|
||||||
|
| ACC_ABSTRACT
|
||||||
|
| ACC_STRICT
|
||||||
|
| ACC_SYNTHETIC
|
||||||
|
| ACC_CONSTRUCTOR
|
||||||
|
| ACC_DECLARED_SYNCHRONIZED)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Method {
|
||||||
|
descriptor,
|
||||||
|
visibility,
|
||||||
|
is_static,
|
||||||
|
is_final,
|
||||||
|
is_synchronized,
|
||||||
|
is_bridge,
|
||||||
|
is_varargs,
|
||||||
|
is_native,
|
||||||
|
is_abstract,
|
||||||
|
is_strictfp,
|
||||||
|
is_synthetic,
|
||||||
|
is_constructor,
|
||||||
|
is_declared_syncrhonized,
|
||||||
|
code: (),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return a list of field from a list of [`EncodedMethod`].
|
||||||
|
///
|
||||||
|
/// # Warning
|
||||||
|
///
|
||||||
|
/// The index of the fields is computed by summing the [`EncodedMethod.field_idx_diff`] of the
|
||||||
|
/// previous element of the list the diff of the current field, so the list must be preserved
|
||||||
|
/// as in the dex file.
|
||||||
|
pub fn get_method_list_from_encoded_field_list(
|
||||||
|
encoded_methods: &[EncodedMethod],
|
||||||
|
dex: &DexFileReader,
|
||||||
|
) -> Result<Vec<Method>> {
|
||||||
|
let mut idx = 0;
|
||||||
|
let mut methods = vec![];
|
||||||
|
for method in encoded_methods {
|
||||||
|
idx += method.method_idx_diff.0;
|
||||||
|
|
||||||
|
methods.push(Self::get_method_from_idx(
|
||||||
|
idx as usize,
|
||||||
|
method.access_flags,
|
||||||
|
method.code_off,
|
||||||
|
dex,
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
Ok(methods)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
use crate::{DexString, Field};
|
use crate::{DexString, Field, Method};
|
||||||
|
|
||||||
/// Represent an apk
|
/// Represent an apk
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
|
@ -46,21 +46,24 @@ pub struct Class {
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub source_file: Option<DexString>,
|
pub source_file: Option<DexString>,
|
||||||
|
|
||||||
|
// TODO: hash map?
|
||||||
/// The static fields
|
/// The static fields
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub static_fields: Vec<Field>,
|
pub static_fields: Vec<Field>,
|
||||||
/// The instance fields
|
/// The instance fields
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub instance_fields: Vec<Field>,
|
pub instance_fields: Vec<Field>,
|
||||||
// /// The static methods
|
/// The direct (static, private or constructor) methods of the class
|
||||||
// #[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
// pub methods: Vec<()>,
|
pub direct_methods: Vec<Method>,
|
||||||
// Dont think we need to distinguish direct (static + private) and virtual (all the other) methods
|
/// The virtual (ie non direct) methods of the class
|
||||||
//
|
#[pyo3(get, set)]
|
||||||
|
pub virtual_methods: Vec<Method>,
|
||||||
|
// Do we need to distinguish direct and virtual (all the other) methods?
|
||||||
|
// Maybe overlapping descriptor (same name, class and proto?)
|
||||||
|
|
||||||
// pub annotations: Option<()> // TODO
|
// pub annotations: Option<()> // TODO
|
||||||
// pub data: Option<()> // TODO
|
// TODO: mix annotation data to fields / methods / class to make it more practicle
|
||||||
// pub static_values: Option<()> // TODO
|
|
||||||
// TODO: mix annotation data and static values to make it more practical
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
|
|
@ -81,6 +84,8 @@ impl Class {
|
||||||
is_enum: false,
|
is_enum: false,
|
||||||
static_fields: vec![],
|
static_fields: vec![],
|
||||||
instance_fields: vec![],
|
instance_fields: vec![],
|
||||||
|
direct_methods: vec![],
|
||||||
|
virtual_methods: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ impl IdMethodType {
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new(return_type: IdType, parameters: Vec<IdType>) -> Self {
|
pub fn new(return_type: IdType, parameters: Vec<IdType>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
shorty: Self::get_shorty(&return_type, ¶meters),
|
shorty: Self::compute_shorty(&return_type, ¶meters),
|
||||||
return_type,
|
return_type,
|
||||||
parameters,
|
parameters,
|
||||||
}
|
}
|
||||||
|
|
@ -43,12 +43,24 @@ impl IdMethodType {
|
||||||
pub fn __repr__(&self) -> String {
|
pub fn __repr__(&self) -> String {
|
||||||
format!("DexMethodType({})", self.__str__())
|
format!("DexMethodType({})", self.__str__())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_shorty(&self) -> DexString {
|
||||||
|
self.shorty.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_return_type(&self) -> IdType {
|
||||||
|
self.return_type.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_parameters(&self) -> Vec<IdType> {
|
||||||
|
self.parameters.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdMethodType {
|
impl IdMethodType {
|
||||||
/// Compute the format for the shorty as described in
|
/// Compute the format for the shorty as described in
|
||||||
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
/// <https://source.android.com/docs/core/runtime/dex-format#shortydescriptor>
|
||||||
pub fn get_shorty(return_type: &IdType, parameters: &[IdType]) -> DexString {
|
pub fn compute_shorty(return_type: &IdType, parameters: &[IdType]) -> DexString {
|
||||||
let mut shorty: String = return_type.get_shorty().into();
|
let mut shorty: String = return_type.get_shorty().into();
|
||||||
for ty in parameters {
|
for ty in parameters {
|
||||||
let ty: String = ty.get_shorty().into();
|
let ty: String = ty.get_shorty().into();
|
||||||
|
|
@ -346,8 +358,11 @@ impl IdField {
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct IdMethod {
|
pub struct IdMethod {
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub class_: IdType,
|
pub class_: IdType,
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub proto: IdMethodType,
|
pub proto: IdMethodType,
|
||||||
|
#[pyo3(get, set)]
|
||||||
pub name: DexString,
|
pub name: DexString,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,39 +11,77 @@ pub struct Method {
|
||||||
/// The structure used to reference this method.
|
/// The structure used to reference this method.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub descriptor: IdMethod,
|
pub descriptor: IdMethod,
|
||||||
/* TODO: ACCESS FLAG
|
/// The field visibility.
|
||||||
/// The field visibility
|
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub visibility: FieldVisibility,
|
pub visibility: MethodVisibility,
|
||||||
/// If the field is defined for the class globally
|
/// Static methods do not take this in argument.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub is_static: bool,
|
pub is_static: bool,
|
||||||
/// If the field is immutable after construction
|
/// Final methods are not averridable.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub is_final: bool,
|
pub is_final: bool,
|
||||||
/// For thread safety
|
/// Synchronized method automatically acquire their associated lock around call.
|
||||||
|
/// Can only be set in native method, (`[Self::is_native] = true`).
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub is_volatile: bool,
|
pub is_synchronized: bool,
|
||||||
/// If the field should **not** be saved by default serialization
|
/// Bridge are automatically added by the compiler as a type-safe bridge.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub is_transient: bool,
|
pub is_bridge: bool,
|
||||||
/// If the field is not defined in the source code
|
/// If the last argument should be treated as a "rest" argument by compiler
|
||||||
|
/// (for method of variable number of argument).
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_varargs: bool,
|
||||||
|
/// If the method is a native method.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_native: bool,
|
||||||
|
/// Abstract methods are not implemented by the class.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_abstract: bool,
|
||||||
|
/// If the method must use strict rules for floating point arithmetic.
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_strictfp: bool,
|
||||||
|
/// Synthetic method are not directly defined in the source code.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub is_synthetic: bool,
|
pub is_synthetic: bool,
|
||||||
/// If the field is an enumerated value
|
/// If the method is a constructor.
|
||||||
#[pyo3(get, set)]
|
#[pyo3(get, set)]
|
||||||
pub is_enum: bool,
|
pub is_constructor: bool,
|
||||||
*/
|
/// If the method is declared as synchronize (just indicatif)
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
pub is_declared_syncrhonized: bool,
|
||||||
|
|
||||||
/// The code of the method
|
/// The code of the method
|
||||||
pub code: (),
|
pub code: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represent the visibility of a field
|
||||||
|
#[pyclass]
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum MethodVisibility {
|
||||||
|
Public,
|
||||||
|
Private,
|
||||||
|
Protected,
|
||||||
|
None_, // Actually quite common
|
||||||
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl Method {
|
impl Method {
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new(descriptor: IdMethod) -> Self {
|
pub fn new(descriptor: IdMethod) -> Self {
|
||||||
Self {
|
Self {
|
||||||
descriptor,
|
descriptor,
|
||||||
|
visibility: MethodVisibility::Public,
|
||||||
|
is_static: false,
|
||||||
|
is_final: false,
|
||||||
|
is_synchronized: false,
|
||||||
|
is_bridge: false,
|
||||||
|
is_varargs: false,
|
||||||
|
is_native: false,
|
||||||
|
is_abstract: false,
|
||||||
|
is_strictfp: false,
|
||||||
|
is_synthetic: false,
|
||||||
|
is_constructor: false,
|
||||||
|
is_declared_syncrhonized: false,
|
||||||
code: (),
|
code: (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue