use crate::python_bindings::{v2_7_15, v3_3_7, v3_5_5, v3_6_6, v3_7_0, v3_8_0};
use std;
pub trait InterpreterState {
type ThreadState: ThreadState;
type Object: Object;
type StringObject: StringObject;
type ListObject: ListObject;
type TupleObject: TupleObject;
fn head(&self) -> * mut Self::ThreadState;
fn modules(&self) -> *mut Self::Object;
}
pub trait ThreadState {
type FrameObject: FrameObject;
type InterpreterState: InterpreterState;
fn interp(&self) -> * mut Self::InterpreterState;
fn frame(&self) -> * mut Self::FrameObject;
fn thread_id(&self) -> u64;
fn next(&self) -> * mut Self;
}
pub trait FrameObject {
type CodeObject: CodeObject;
fn code(&self) -> * mut Self::CodeObject;
fn lasti(&self) -> i32;
fn back(&self) -> * mut Self;
}
pub trait CodeObject {
type StringObject: StringObject;
type BytesObject: BytesObject;
type TupleObject: TupleObject;
fn name(&self) -> * mut Self::StringObject;
fn filename(&self) -> * mut Self::StringObject;
fn lnotab(&self) -> * mut Self::BytesObject;
fn first_lineno(&self) -> i32;
fn nlocals(&self) -> i32;
fn argcount(&self) -> i32;
fn varnames(&self) -> * mut Self::TupleObject;
}
pub trait BytesObject {
fn size(&self) -> usize;
fn address(&self, base: usize) -> usize;
}
pub trait StringObject {
fn ascii(&self) -> bool;
fn kind(&self) -> u32;
fn size(&self) -> usize;
fn address(&self, base: usize) -> usize;
}
pub trait TupleObject {
fn size(&self) -> usize;
fn address(&self, base: usize, index: usize) -> usize;
}
pub trait ListObject {
type Object: Object;
fn size(&self) -> usize;
fn item(&self) -> *mut *mut Self::Object;
}
pub trait Object {
type TypeObject: TypeObject;
fn ob_type(&self) -> * mut Self::TypeObject;
}
pub trait TypeObject {
fn name(&self) -> *const ::std::os::raw::c_char;
fn dictoffset(&self) -> isize;
fn flags(&self) -> usize;
}
fn offset_of<T, M>(object: *const T, member: *const M) -> usize {
member as usize - object as usize
}
macro_rules! PythonCommonImpl {
($py: ident, $bytesobject: ident, $stringobject: ident) => (
impl InterpreterState for $py::PyInterpreterState {
type ThreadState = $py::PyThreadState;
type Object = $py::PyObject;
type StringObject = $py::$stringobject;
type ListObject = $py::PyListObject;
type TupleObject = $py::PyTupleObject;
fn head(&self) -> * mut Self::ThreadState { self.tstate_head }
fn modules(&self) -> * mut Self::Object { self.modules }
}
impl ThreadState for $py::PyThreadState {
type FrameObject = $py::PyFrameObject;
type InterpreterState = $py::PyInterpreterState;
fn frame(&self) -> * mut Self::FrameObject { self.frame }
fn thread_id(&self) -> u64 { self.thread_id as u64 }
fn next(&self) -> * mut Self { self.next }
fn interp(&self) -> *mut Self::InterpreterState { self.interp }
}
impl FrameObject for $py::PyFrameObject {
type CodeObject = $py::PyCodeObject;
fn code(&self) -> * mut Self::CodeObject { self.f_code }
fn lasti(&self) -> i32 { self.f_lasti }
fn back(&self) -> * mut Self { self.f_back }
}
impl CodeObject for $py::PyCodeObject {
type BytesObject = $py::$bytesobject;
type StringObject = $py::$stringobject;
type TupleObject = $py::PyTupleObject;
fn name(&self) -> * mut Self::StringObject { self.co_name as * mut Self::StringObject }
fn filename(&self) -> * mut Self::StringObject { self.co_filename as * mut Self::StringObject }
fn lnotab(&self) -> * mut Self::BytesObject { self.co_lnotab as * mut Self::BytesObject }
fn first_lineno(&self) -> i32 { self.co_firstlineno }
fn nlocals(&self) -> i32 { self.co_nlocals }
fn argcount(&self) -> i32 { self.co_argcount }
fn varnames(&self) -> * mut Self::TupleObject { self.co_varnames as * mut Self::TupleObject }
}
impl Object for $py::PyObject {
type TypeObject = $py::PyTypeObject;
fn ob_type(&self) -> * mut Self::TypeObject { self.ob_type as * mut Self::TypeObject }
}
impl TypeObject for $py::PyTypeObject {
fn name(&self) -> *const ::std::os::raw::c_char { self.tp_name }
fn dictoffset(&self) -> isize { self.tp_dictoffset }
fn flags(&self) -> usize { self.tp_flags as usize }
}
)
}
macro_rules! Python3Impl {
($py: ident) => (
impl BytesObject for $py::PyBytesObject {
fn size(&self) -> usize { self.ob_base.ob_size as usize }
fn address(&self, base: usize) -> usize {
base + offset_of(self, &self.ob_sval)
}
}
impl StringObject for $py::PyUnicodeObject {
fn ascii(&self) -> bool { self._base._base.state.ascii() != 0 }
fn size(&self) -> usize { self._base._base.length as usize }
fn kind(&self) -> u32 { self._base._base.state.kind() }
fn address(&self, base: usize) -> usize {
if self._base._base.state.compact() == 0 {
return unsafe{ self.data.any as usize };
}
if self._base._base.state.ascii() == 1 {
base + std::mem::size_of::<$py::PyASCIIObject>()
} else {
base + std::mem::size_of::<$py::PyCompactUnicodeObject>()
}
}
}
impl ListObject for $py::PyListObject {
type Object = $py::PyObject;
fn size(&self) -> usize { self.ob_base.ob_size as usize }
fn item(&self) -> *mut *mut Self::Object { self.ob_item }
}
impl TupleObject for $py::PyTupleObject {
fn size(&self) -> usize { self.ob_base.ob_size as usize }
fn address(&self, base: usize, index: usize) -> usize {
base + offset_of(self, &self.ob_item) + index * std::mem::size_of::<* mut $py::PyObject>()
}
}
)
}
PythonCommonImpl!(v3_8_0, PyBytesObject, PyUnicodeObject);
Python3Impl!(v3_8_0);
PythonCommonImpl!(v3_7_0, PyBytesObject, PyUnicodeObject);
Python3Impl!(v3_7_0);
PythonCommonImpl!(v3_6_6, PyBytesObject, PyUnicodeObject);
Python3Impl!(v3_6_6);
PythonCommonImpl!(v3_5_5, PyBytesObject, PyUnicodeObject);
Python3Impl!(v3_5_5);
PythonCommonImpl!(v3_3_7, PyBytesObject, PyUnicodeObject);
Python3Impl!(v3_3_7);
PythonCommonImpl!(v2_7_15, PyStringObject, PyStringObject);
impl BytesObject for v2_7_15::PyStringObject {
fn size(&self) -> usize { self.ob_size as usize }
fn address(&self, base: usize) -> usize { base + offset_of(self, &self.ob_sval) }
}
impl StringObject for v2_7_15::PyStringObject {
fn ascii(&self) -> bool { true }
fn kind(&self) -> u32 { 1 }
fn size(&self) -> usize { self.ob_size as usize }
fn address(&self, base: usize) -> usize { base + offset_of(self, &self.ob_sval) }
}
impl ListObject for v2_7_15::PyListObject {
type Object = v2_7_15::PyObject;
fn size(&self) -> usize { self.ob_size as usize }
fn item(&self) -> *mut *mut Self::Object { self.ob_item }
}
impl TupleObject for v2_7_15::PyTupleObject {
fn size(&self) -> usize { self.ob_size as usize }
fn address(&self, base: usize, index: usize) -> usize {
base + offset_of(self, &self.ob_item) + index * std::mem::size_of::<* mut v2_7_15::PyObject>()
}
}