2017-05-16 05:24:06 +00:00
|
|
|
// Copyright (c) 2017-present PyO3 Project and Contributors
|
|
|
|
|
2017-06-09 19:30:13 +00:00
|
|
|
use std;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
use syn;
|
2017-07-27 05:29:55 +00:00
|
|
|
use quote::{Tokens, ToTokens};
|
2017-05-16 05:24:06 +00:00
|
|
|
|
2017-06-13 00:15:26 +00:00
|
|
|
use utils;
|
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
|
2017-06-09 19:30:13 +00:00
|
|
|
pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
2017-07-27 05:29:55 +00:00
|
|
|
let (params, flags, base_cls) = parse_attribute(attr);
|
2017-06-18 15:00:27 +00:00
|
|
|
let doc = utils::get_doc(&ast.attrs, true);
|
2017-06-09 19:30:13 +00:00
|
|
|
|
2017-06-24 15:28:31 +00:00
|
|
|
let base = syn::Ident::from("_pyo3::PyObjectRef");
|
2017-05-28 05:45:48 +00:00
|
|
|
let mut token: Option<syn::Ident> = None;
|
2017-05-17 06:43:39 +00:00
|
|
|
|
|
|
|
match ast.body {
|
2017-05-28 05:45:48 +00:00
|
|
|
syn::Body::Struct(syn::VariantData::Struct(ref mut fields)) => {
|
2017-06-01 16:45:00 +00:00
|
|
|
for field in fields.iter() {
|
|
|
|
if is_python_token(field) {
|
|
|
|
token = field.ident.clone();
|
|
|
|
break
|
2017-05-28 05:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-27 17:49:38 +00:00
|
|
|
},
|
2017-06-18 15:41:20 +00:00
|
|
|
_ => panic!("#[class] can only be used with normal structs"),
|
2017-05-17 06:43:39 +00:00
|
|
|
}
|
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_CLS_{}", ast.ident));
|
2017-07-27 05:29:55 +00:00
|
|
|
let tokens = impl_class(&ast.ident, &base, token, doc, params, flags, base_cls);
|
2017-05-23 06:19:14 +00:00
|
|
|
|
2017-05-16 05:24:06 +00:00
|
|
|
quote! {
|
2017-05-18 21:46:29 +00:00
|
|
|
#[allow(non_upper_case_globals, unused_attributes,
|
|
|
|
unused_qualifications, unused_variables, non_camel_case_types)]
|
2017-05-16 05:24:06 +00:00
|
|
|
const #dummy_const: () = {
|
2017-06-01 22:06:48 +00:00
|
|
|
use std;
|
2017-05-18 18:15:06 +00:00
|
|
|
extern crate pyo3 as _pyo3;
|
2017-05-16 05:24:06 +00:00
|
|
|
|
|
|
|
#tokens
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-09 19:30:13 +00:00
|
|
|
fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
2017-06-13 00:15:26 +00:00
|
|
|
token: Option<syn::Ident>, doc: syn::Lit,
|
2017-07-27 05:29:55 +00:00
|
|
|
params: HashMap<&'static str, syn::Ident>,
|
|
|
|
flags: Vec<syn::Ident>, base_cls: Option<(String, String)>) -> Tokens {
|
2017-06-09 19:30:13 +00:00
|
|
|
let cls_name = match params.get("name") {
|
|
|
|
Some(name) => quote! { #name }.as_str().to_string(),
|
|
|
|
None => quote! { #cls }.as_str().to_string()
|
|
|
|
};
|
2017-05-18 23:57:39 +00:00
|
|
|
|
2017-07-14 23:21:18 +00:00
|
|
|
let extra = if let Some(token) = token {
|
2017-05-28 05:45:48 +00:00
|
|
|
Some(quote! {
|
2017-06-01 22:06:48 +00:00
|
|
|
impl _pyo3::PyObjectWithToken for #cls {
|
2017-07-14 21:21:07 +00:00
|
|
|
#[inline(always)]
|
2017-07-14 02:04:00 +00:00
|
|
|
fn py<'p>(&'p self) -> _pyo3::Python<'p> {
|
2017-07-14 23:21:18 +00:00
|
|
|
self.#token.py()
|
2017-05-28 05:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-23 22:03:52 +00:00
|
|
|
impl _pyo3::ToPyObject for #cls {
|
|
|
|
#[inline]
|
|
|
|
fn to_object<'p>(&self, py: _pyo3::Python<'p>) -> _pyo3::PyObject {
|
|
|
|
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
|
|
|
}
|
2017-07-26 08:11:00 +00:00
|
|
|
}
|
|
|
|
impl _pyo3::ToBorrowedObject for #cls {
|
2017-06-23 22:03:52 +00:00
|
|
|
#[inline]
|
|
|
|
fn with_borrowed_ptr<F, R>(&self, _py: _pyo3::Python, f: F) -> R
|
|
|
|
where F: FnOnce(*mut ffi::PyObject) -> R
|
|
|
|
{
|
|
|
|
f(self.as_ptr())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a> _pyo3::ToPyObject for &'a mut #cls {
|
2017-06-20 03:55:07 +00:00
|
|
|
#[inline]
|
2017-06-23 03:56:09 +00:00
|
|
|
fn to_object<'p>(&self, py: _pyo3::Python<'p>) -> _pyo3::PyObject {
|
|
|
|
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
2017-06-20 03:55:07 +00:00
|
|
|
}
|
2017-07-26 08:11:00 +00:00
|
|
|
}
|
|
|
|
impl<'a> _pyo3::ToBorrowedObject for &'a mut #cls {
|
2017-06-20 03:55:07 +00:00
|
|
|
#[inline]
|
|
|
|
fn with_borrowed_ptr<F, R>(&self, _py: _pyo3::Python, f: F) -> R
|
|
|
|
where F: FnOnce(*mut ffi::PyObject) -> R
|
|
|
|
{
|
|
|
|
f(self.as_ptr())
|
|
|
|
}
|
|
|
|
}
|
2017-06-20 06:57:34 +00:00
|
|
|
impl<'a> _pyo3::IntoPyObject for &'a #cls
|
|
|
|
{
|
|
|
|
#[inline]
|
2017-06-23 03:56:09 +00:00
|
|
|
fn into_object<'p>(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
|
|
|
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
2017-06-20 06:57:34 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-23 22:03:52 +00:00
|
|
|
impl<'a> _pyo3::IntoPyObject for &'a mut #cls
|
|
|
|
{
|
|
|
|
#[inline]
|
|
|
|
fn into_object<'p>(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
|
|
|
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a> std::convert::From<&'a mut #cls> for &'a #cls
|
|
|
|
{
|
|
|
|
fn from(ob: &'a mut #cls) -> Self {
|
|
|
|
unsafe{std::mem::transmute(ob)}
|
|
|
|
}
|
|
|
|
}
|
2017-06-20 03:55:07 +00:00
|
|
|
impl _pyo3::ToPyPointer for #cls {
|
|
|
|
#[inline]
|
|
|
|
fn as_ptr(&self) -> *mut ffi::PyObject {
|
|
|
|
unsafe {
|
2017-07-21 16:48:48 +00:00
|
|
|
{self as *const _ as *mut u8}
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::offset())
|
|
|
|
as *mut ffi::PyObject
|
2017-06-20 03:55:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-06-22 08:04:37 +00:00
|
|
|
impl std::fmt::Debug for #cls {
|
2017-05-28 05:45:48 +00:00
|
|
|
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
2017-06-22 08:04:37 +00:00
|
|
|
use pyo3::ObjectProtocol;
|
|
|
|
let s = try!(self.repr().map_err(|_| std::fmt::Error));
|
2017-06-21 22:11:32 +00:00
|
|
|
f.write_str(&s.to_string_lossy())
|
2017-05-28 05:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-22 08:04:37 +00:00
|
|
|
impl std::fmt::Display for #cls {
|
2017-05-28 05:45:48 +00:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
2017-06-22 08:04:37 +00:00
|
|
|
use pyo3::ObjectProtocol;
|
|
|
|
let s = try!(self.str().map_err(|_| std::fmt::Error));
|
2017-06-21 22:11:32 +00:00
|
|
|
f.write_str(&s.to_string_lossy())
|
2017-05-28 05:45:48 +00:00
|
|
|
}
|
2017-05-28 15:57:34 +00:00
|
|
|
}
|
2017-05-28 05:45:48 +00:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2017-06-09 21:27:37 +00:00
|
|
|
let extra = {
|
|
|
|
if let Some(freelist) = params.get("freelist") {
|
|
|
|
Some(quote! {
|
|
|
|
impl _pyo3::freelist::PyObjectWithFreeList for #cls {
|
|
|
|
#[inline]
|
2017-07-18 17:53:02 +00:00
|
|
|
fn get_free_list() -> &'static mut _pyo3::freelist::FreeList<*mut _pyo3::ffi::PyObject> {
|
|
|
|
static mut FREELIST: *mut _pyo3::freelist::FreeList<*mut _pyo3::ffi::PyObject> = 0 as *mut _;
|
2017-06-09 21:27:37 +00:00
|
|
|
unsafe {
|
|
|
|
if FREELIST.is_null() {
|
|
|
|
FREELIST = Box::into_raw(Box::new(
|
|
|
|
_pyo3::freelist::FreeList::with_capacity(#freelist)));
|
|
|
|
|
2017-07-26 01:11:45 +00:00
|
|
|
<#cls as _pyo3::typeob::PyTypeObject>::init_type();
|
2017-06-09 21:27:37 +00:00
|
|
|
}
|
2017-07-18 14:10:56 +00:00
|
|
|
&mut *FREELIST
|
2017-06-09 21:27:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#extra
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
extra
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-24 20:03:18 +00:00
|
|
|
// insert space for weak ref
|
|
|
|
let mut has_weakref = false;
|
|
|
|
for f in flags.iter() {
|
|
|
|
if *f == syn::Ident::from("_pyo3::typeob::PY_TYPE_FLAG_WEAKREF") {
|
|
|
|
has_weakref = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let weakref = if has_weakref {
|
|
|
|
syn::Ident::from("std::mem::size_of::<*const _pyo3::ffi::PyObject>()")
|
|
|
|
} else {
|
|
|
|
syn::Ident::from("0")
|
|
|
|
};
|
|
|
|
|
2017-07-27 05:29:55 +00:00
|
|
|
// base class
|
|
|
|
let offset_code = if let Some((m, cls_name)) = base_cls {
|
|
|
|
quote! {
|
|
|
|
#[inline]
|
|
|
|
unsafe fn base_type_object() -> &'static mut ffi::PyTypeObject {
|
|
|
|
static mut TYPE_OBJECT: *mut ffi::PyTypeObject = 0 as *mut ffi::PyTypeObject;
|
|
|
|
|
|
|
|
if TYPE_OBJECT.is_null() {
|
|
|
|
// load module
|
|
|
|
let gil = _pyo3::Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
|
|
|
let imp = py.import(#m)
|
2017-07-27 23:14:54 +00:00
|
|
|
.map_err(|e| e.print(py))
|
2017-07-27 05:29:55 +00:00
|
|
|
.expect(format!(
|
|
|
|
"Can not import module: {}", #m).as_ref());
|
|
|
|
let cls = imp.get(#cls_name)
|
2017-07-27 23:14:54 +00:00
|
|
|
.map_err(|e| e.print(py))
|
2017-07-27 05:29:55 +00:00
|
|
|
.expect(format!(
|
|
|
|
"Can not load exception class: {}.{}", #m, #cls_name).as_ref());
|
|
|
|
TYPE_OBJECT = cls.into_ptr() as *mut ffi::PyTypeObject;
|
|
|
|
}
|
|
|
|
&mut *TYPE_OBJECT
|
|
|
|
}
|
|
|
|
#[inline]
|
|
|
|
fn offset() -> isize {
|
|
|
|
static mut OFFSET: isize = 0;
|
|
|
|
unsafe {
|
|
|
|
if OFFSET == 0 {
|
|
|
|
// round base_size up to next multiple of align
|
|
|
|
OFFSET = (
|
|
|
|
((Self::base_type_object().tp_basicsize as usize) +
|
|
|
|
std::mem::align_of::<#cls>()-1) /
|
|
|
|
std::mem::align_of::<#cls>() * std::mem::align_of::<#cls>())
|
|
|
|
as isize
|
|
|
|
}
|
|
|
|
OFFSET
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
quote! {
|
|
|
|
#[inline]
|
|
|
|
fn offset() -> isize {
|
|
|
|
static mut OFFSET: isize = 0;
|
|
|
|
unsafe {
|
|
|
|
if OFFSET == 0 {
|
|
|
|
// round base_size up to next multiple of align
|
|
|
|
OFFSET = (
|
|
|
|
(<#base as _pyo3::typeob::PyTypeInfo>::size() +
|
|
|
|
std::mem::align_of::<#cls>()-1) /
|
|
|
|
std::mem::align_of::<#cls>() * std::mem::align_of::<#cls>())
|
|
|
|
as isize
|
|
|
|
}
|
|
|
|
OFFSET
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-17 06:43:39 +00:00
|
|
|
quote! {
|
2017-05-25 05:43:07 +00:00
|
|
|
impl _pyo3::typeob::PyTypeInfo for #cls {
|
2017-05-23 06:19:14 +00:00
|
|
|
type Type = #cls;
|
2017-07-13 23:45:50 +00:00
|
|
|
const NAME: &'static str = #cls_name;
|
|
|
|
const DESCRIPTION: &'static str = #doc;
|
2017-07-27 05:29:55 +00:00
|
|
|
const FLAGS: usize = #(#flags)|*;
|
2017-05-23 06:19:14 +00:00
|
|
|
|
2017-07-27 05:29:55 +00:00
|
|
|
#[inline]
|
|
|
|
fn size() -> usize {
|
|
|
|
static mut SIZE: usize = 0;
|
2017-05-17 06:43:39 +00:00
|
|
|
|
2017-07-27 05:29:55 +00:00
|
|
|
unsafe {
|
|
|
|
if SIZE == 0 {
|
|
|
|
SIZE = Self::offset() as usize + std::mem::size_of::<#cls>() + #weakref;
|
|
|
|
}
|
|
|
|
SIZE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#offset_code
|
2017-07-24 19:19:05 +00:00
|
|
|
|
2017-05-17 06:43:39 +00:00
|
|
|
#[inline]
|
2017-07-13 23:45:50 +00:00
|
|
|
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
|
2017-05-18 18:15:06 +00:00
|
|
|
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
|
2017-07-13 23:45:50 +00:00
|
|
|
&mut TYPE_OBJECT
|
2017-05-17 06:43:39 +00:00
|
|
|
}
|
2017-06-20 18:59:07 +00:00
|
|
|
|
|
|
|
#[inline]
|
2017-07-18 17:53:02 +00:00
|
|
|
fn is_instance(ptr: *mut _pyo3::ffi::PyObject) -> bool {
|
|
|
|
unsafe {_pyo3::ffi::PyObject_TypeCheck(
|
2017-06-20 18:59:07 +00:00
|
|
|
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0}
|
|
|
|
}
|
2017-05-17 06:43:39 +00:00
|
|
|
}
|
2017-05-25 05:43:07 +00:00
|
|
|
|
2017-06-08 21:21:48 +00:00
|
|
|
impl _pyo3::typeob::PyTypeObject for #cls {
|
|
|
|
#[inline(always)]
|
2017-07-26 01:11:45 +00:00
|
|
|
fn init_type() {
|
2017-06-08 21:21:48 +00:00
|
|
|
static START: std::sync::Once = std::sync::ONCE_INIT;
|
|
|
|
START.call_once(|| {
|
2017-07-26 01:11:45 +00:00
|
|
|
let ty = unsafe{<#cls as _pyo3::typeob::PyTypeInfo>::type_object()};
|
2017-06-08 21:21:48 +00:00
|
|
|
|
|
|
|
if (ty.tp_flags & _pyo3::ffi::Py_TPFLAGS_READY) == 0 {
|
2017-07-26 01:11:45 +00:00
|
|
|
let gil = _pyo3::Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
2017-06-08 21:21:48 +00:00
|
|
|
// automatically initialize the class on-demand
|
2017-07-26 01:11:45 +00:00
|
|
|
_pyo3::typeob::initialize_type::<#cls>(py, None).expect(
|
2017-06-13 00:15:26 +00:00
|
|
|
format!("An error occurred while initializing class {}",
|
2017-07-13 23:45:50 +00:00
|
|
|
<#cls as _pyo3::typeob::PyTypeInfo>::NAME).as_ref());
|
2017-06-08 21:21:48 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-15 18:13:58 +00:00
|
|
|
impl _pyo3::PyDowncastFrom for #cls
|
2017-05-29 09:47:27 +00:00
|
|
|
{
|
2017-07-19 20:01:59 +00:00
|
|
|
fn try_downcast_from(ob: &_pyo3::PyObjectRef) -> Option<&#cls>
|
2017-05-29 09:47:27 +00:00
|
|
|
{
|
|
|
|
unsafe {
|
2017-07-19 20:01:59 +00:00
|
|
|
let ptr = ob.as_ptr();
|
2017-05-29 09:47:27 +00:00
|
|
|
let checked = ffi::PyObject_TypeCheck(
|
2017-07-19 20:01:59 +00:00
|
|
|
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
2017-05-29 09:47:27 +00:00
|
|
|
|
|
|
|
if checked {
|
2017-07-21 16:48:48 +00:00
|
|
|
let ptr = (ptr as *mut u8)
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
2017-07-19 20:01:59 +00:00
|
|
|
Some(ptr.as_ref().unwrap())
|
2017-05-29 09:47:27 +00:00
|
|
|
} else {
|
2017-07-19 20:01:59 +00:00
|
|
|
None
|
2017-05-29 09:47:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-06-21 06:26:28 +00:00
|
|
|
|
2017-07-19 20:01:59 +00:00
|
|
|
fn try_exact_downcast_from(ob: &_pyo3::PyObjectRef) -> Option<&#cls>
|
|
|
|
{
|
|
|
|
unsafe {
|
|
|
|
let ptr = ob.as_ptr();
|
|
|
|
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
|
|
|
{
|
2017-07-21 16:48:48 +00:00
|
|
|
let ptr = (ptr as *mut u8)
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
2017-07-19 20:01:59 +00:00
|
|
|
Some(ptr.as_ref().unwrap())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2017-06-24 15:28:31 +00:00
|
|
|
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
2017-06-22 08:04:37 +00:00
|
|
|
{
|
2017-07-21 16:48:48 +00:00
|
|
|
let ptr = (ob.as_ptr() as *mut u8)
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
2017-07-18 11:28:49 +00:00
|
|
|
&*ptr
|
2017-06-22 08:04:37 +00:00
|
|
|
}
|
2017-07-19 20:01:59 +00:00
|
|
|
#[inline]
|
2017-06-24 15:28:31 +00:00
|
|
|
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
|
2017-06-21 06:26:28 +00:00
|
|
|
{
|
2017-07-21 16:48:48 +00:00
|
|
|
let ptr = (ob.as_ptr() as *mut u8)
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
2017-07-18 11:28:49 +00:00
|
|
|
&mut *ptr
|
2017-06-21 06:26:28 +00:00
|
|
|
}
|
2017-05-29 09:47:27 +00:00
|
|
|
}
|
2017-06-15 18:13:58 +00:00
|
|
|
impl _pyo3::PyMutDowncastFrom for #cls
|
2017-06-06 03:25:00 +00:00
|
|
|
{
|
2017-07-19 20:01:59 +00:00
|
|
|
fn try_mut_downcast_from(ob: &mut _pyo3::PyObjectRef) -> Option<&mut #cls>
|
2017-06-06 03:25:00 +00:00
|
|
|
{
|
|
|
|
unsafe {
|
2017-07-19 20:01:59 +00:00
|
|
|
let ptr = ob.as_ptr();
|
2017-06-06 03:25:00 +00:00
|
|
|
let checked = ffi::PyObject_TypeCheck(
|
2017-07-19 20:01:59 +00:00
|
|
|
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
2017-06-06 03:25:00 +00:00
|
|
|
|
|
|
|
if checked {
|
2017-07-21 16:48:48 +00:00
|
|
|
let ptr = (ptr as *mut u8)
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
2017-07-19 20:01:59 +00:00
|
|
|
Some(ptr.as_mut().unwrap())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn try_mut_exact_downcast_from(ob: &mut _pyo3::PyObjectRef) -> Option<&mut #cls>
|
|
|
|
{
|
|
|
|
unsafe {
|
|
|
|
let ptr = ob.as_ptr();
|
|
|
|
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
|
|
|
{
|
2017-07-21 16:48:48 +00:00
|
|
|
let ptr = (ptr as *mut u8)
|
2017-07-27 05:29:55 +00:00
|
|
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
2017-07-19 20:01:59 +00:00
|
|
|
Some(ptr.as_mut().unwrap())
|
2017-06-06 03:25:00 +00:00
|
|
|
} else {
|
2017-07-19 20:01:59 +00:00
|
|
|
None
|
2017-06-06 03:25:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-05-30 05:59:03 +00:00
|
|
|
|
2017-05-28 05:45:48 +00:00
|
|
|
#extra
|
2017-05-16 05:24:06 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-01 16:45:00 +00:00
|
|
|
|
|
|
|
fn is_python_token(field: &syn::Field) -> bool {
|
|
|
|
match field.ty {
|
|
|
|
syn::Ty::Path(_, ref path) => {
|
|
|
|
if let Some(segment) = path.segments.last() {
|
2017-06-01 22:06:48 +00:00
|
|
|
return segment.ident.as_ref() == "PyToken"
|
2017-06-01 16:45:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2017-06-09 19:30:13 +00:00
|
|
|
|
2017-07-27 05:29:55 +00:00
|
|
|
fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
|
|
|
Vec<syn::Ident>, Option<(String, String)>) {
|
2017-06-09 19:30:13 +00:00
|
|
|
let mut params = HashMap::new();
|
2017-07-24 19:19:05 +00:00
|
|
|
let mut flags = vec![syn::Ident::from("0")];
|
2017-07-27 05:29:55 +00:00
|
|
|
let mut base = None;
|
2017-06-09 19:30:13 +00:00
|
|
|
|
|
|
|
if let Ok(tts) = syn::parse_token_trees(&attr) {
|
2017-06-09 19:35:29 +00:00
|
|
|
let mut elem = Vec::new();
|
2017-06-09 19:30:13 +00:00
|
|
|
let mut elems = Vec::new();
|
|
|
|
|
|
|
|
for tt in tts.iter() {
|
|
|
|
match tt {
|
|
|
|
&syn::TokenTree::Token(_) => {
|
|
|
|
println!("Wrong format: {:?}", attr.to_string());
|
|
|
|
}
|
|
|
|
&syn::TokenTree::Delimited(ref delimited) => {
|
|
|
|
for tt in delimited.tts.iter() {
|
|
|
|
match tt {
|
|
|
|
&syn::TokenTree::Token(syn::Token::Comma) => {
|
|
|
|
let el = std::mem::replace(&mut elem, Vec::new());
|
|
|
|
elems.push(el);
|
|
|
|
},
|
|
|
|
_ => elem.push(tt.clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-06-09 19:35:29 +00:00
|
|
|
if !elem.is_empty() {
|
|
|
|
elems.push(elem);
|
|
|
|
}
|
2017-06-09 19:30:13 +00:00
|
|
|
|
|
|
|
for elem in elems {
|
|
|
|
let key = match elem[0] {
|
|
|
|
syn::TokenTree::Token(syn::Token::Ident(ref ident)) => {
|
|
|
|
ident.as_ref().to_owned().to_lowercase()
|
|
|
|
},
|
|
|
|
_ => {
|
|
|
|
println!("Wrong format: {:?}", attr.to_string());
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-24 19:19:05 +00:00
|
|
|
if elem.len() == 1 {
|
|
|
|
match key.as_ref() {
|
|
|
|
"gc" => {
|
|
|
|
flags.push(syn::Ident::from("_pyo3::typeob::PY_TYPE_FLAG_GC"));
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
"weakref" => {
|
|
|
|
flags.push(syn::Ident::from("_pyo3::typeob::PY_TYPE_FLAG_WEAKREF"));
|
|
|
|
continue
|
|
|
|
}
|
2017-07-27 15:05:15 +00:00
|
|
|
"subclass" => {
|
|
|
|
flags.push(syn::Ident::from("_pyo3::typeob::PY_TYPE_FLAG_BASETYPE"));
|
|
|
|
continue
|
|
|
|
}
|
2017-07-24 19:19:05 +00:00
|
|
|
_ => {
|
|
|
|
println!("Unsupported parameter: {:?}", key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if elem.len() < 3 {
|
|
|
|
println!("Wrong format: {:?}", elem);
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-06-09 19:30:13 +00:00
|
|
|
match elem[1] {
|
|
|
|
syn::TokenTree::Token(syn::Token::Eq) => (),
|
|
|
|
_ => {
|
|
|
|
println!("Wrong format: {:?}", attr.to_string());
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match key.as_ref() {
|
|
|
|
"freelist" => {
|
|
|
|
if elem.len() != 3 {
|
|
|
|
println!("Wrong 'freelist' format: {:?}", elem);
|
|
|
|
} else {
|
|
|
|
match elem[2] {
|
|
|
|
syn::TokenTree::Token(
|
|
|
|
syn::Token::Literal(
|
|
|
|
syn::Lit::Int(val, _))) => {
|
|
|
|
params.insert("freelist", syn::Ident::from(val.to_string()));
|
|
|
|
}
|
|
|
|
_ => println!("Wrong 'freelist' format: {:?}", elem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"name" => {
|
|
|
|
if elem.len() != 3 {
|
|
|
|
println!("Wrong 'name' format: {:?}", elem);
|
|
|
|
} else {
|
|
|
|
match elem[2] {
|
|
|
|
syn::TokenTree::Token(syn::Token::Ident(ref ident)) => {
|
|
|
|
params.insert("name", ident.clone());
|
|
|
|
},
|
|
|
|
_ => println!("Wrong 'name' format: {:?}", elem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"base" => {
|
2017-07-27 05:29:55 +00:00
|
|
|
let mut m = String::new();
|
|
|
|
for el in elem[2..elem.len()-1].iter() {
|
|
|
|
let mut t = Tokens::new();
|
|
|
|
el.to_tokens(&mut t);
|
|
|
|
m += t.as_str().trim();
|
|
|
|
}
|
|
|
|
m = m.trim_matches('.').to_owned();
|
|
|
|
let mut t = Tokens::new();
|
|
|
|
elem[elem.len()-1].to_tokens(&mut t);
|
|
|
|
let cls = t.as_str().trim().to_owned();
|
|
|
|
base = Some((m, cls));
|
2017-07-24 19:19:05 +00:00
|
|
|
},
|
2017-06-09 19:30:13 +00:00
|
|
|
_ => {
|
|
|
|
println!("Unsupported parameter: {:?}", key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-07-24 19:19:05 +00:00
|
|
|
|
2017-07-27 05:29:55 +00:00
|
|
|
(params, flags, base)
|
2017-06-09 19:30:13 +00:00
|
|
|
}
|