use std;
use std::ffi::CString;
use ffi;
use libc::c_int;
static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
#[derive(Debug)]
pub enum PyMethodDefType {
New(PyMethodDef),
Init(PyMethodDef),
Call(PyMethodDef),
Class(PyMethodDef),
Static(PyMethodDef),
Method(PyMethodDef),
Getter(PyGetterDef),
Setter(PySetterDef),
}
#[derive(Copy, Clone, Debug)]
pub enum PyMethodType {
PyCFunction(ffi::PyCFunction),
PyCFunctionWithKeywords(ffi::PyCFunctionWithKeywords),
PyNoArgsFunction(ffi::PyNoArgsFunction),
PyNewFunc(ffi::newfunc),
PyInitFunc(ffi::initproc),
}
#[derive(Copy, Clone, Debug)]
pub struct PyMethodDef {
pub ml_name: &'static str,
pub ml_meth: PyMethodType,
pub ml_flags: c_int,
pub ml_doc: &'static str,
}
#[derive(Copy, Clone, Debug)]
pub struct PyGetterDef {
pub name: &'static str,
pub meth: ffi::getter,
pub doc: &'static str,
}
#[derive(Copy, Clone, Debug)]
pub struct PySetterDef {
pub name: &'static str,
pub meth: ffi::setter,
pub doc: &'static str,
}
unsafe impl Sync for PyMethodDef {}
unsafe impl Sync for ffi::PyMethodDef {}
unsafe impl Sync for PyGetterDef {}
unsafe impl Sync for PySetterDef {}
unsafe impl Sync for ffi::PyGetSetDef {}
impl PyMethodDef {
pub fn as_method_def(&self) -> ffi::PyMethodDef {
let meth = match self.ml_meth {
PyMethodType::PyCFunction(meth) => meth,
PyMethodType::PyCFunctionWithKeywords(meth) => unsafe {
std::mem::transmute::<ffi::PyCFunctionWithKeywords, ffi::PyCFunction>(meth)
},
PyMethodType::PyNoArgsFunction(meth) => unsafe {
std::mem::transmute::<ffi::PyNoArgsFunction, ffi::PyCFunction>(meth)
},
PyMethodType::PyNewFunc(meth) => unsafe {
std::mem::transmute::<ffi::newfunc, ffi::PyCFunction>(meth)
},
PyMethodType::PyInitFunc(meth) => unsafe {
std::mem::transmute::<ffi::initproc, ffi::PyCFunction>(meth)
},
};
ffi::PyMethodDef {
ml_name: CString::new(self.ml_name)
.expect("Method name must not contain NULL byte")
.into_raw(),
ml_meth: Some(meth),
ml_flags: self.ml_flags,
ml_doc: self.ml_doc.as_ptr() as *const _,
}
}
}
impl PyGetterDef {
pub fn copy_to(&self, dst: &mut ffi::PyGetSetDef) {
if dst.name.is_null() {
dst.name = CString::new(self.name)
.expect("Method name must not contain NULL byte")
.into_raw();
}
dst.get = Some(self.meth);
}
}
impl PySetterDef {
pub fn copy_to(&self, dst: &mut ffi::PyGetSetDef) {
if dst.name.is_null() {
dst.name = CString::new(self.name)
.expect("Method name must not contain NULL byte")
.into_raw();
}
dst.set = Some(self.meth);
}
}
#[doc(hidden)]
pub trait PyMethodsProtocolImpl {
fn py_methods() -> &'static [PyMethodDefType];
}
impl<T> PyMethodsProtocolImpl for T {
default fn py_methods() -> &'static [PyMethodDefType] {
NO_PY_METHODS
}
}
#[doc(hidden)]
pub trait PyPropMethodsProtocolImpl {
fn py_methods() -> &'static [PyMethodDefType];
}
impl<T> PyPropMethodsProtocolImpl for T {
default fn py_methods() -> &'static [PyMethodDefType] {
NO_PY_METHODS
}
}