diff --git a/src/lib.rs b/src/lib.rs index c6137711..73cbde8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,11 @@ -#![feature(core)] -#![feature(unsafe_destructor)] -#![feature(unsafe_no_drop_flag)] -#![feature(optin_builtin_traits)] -#![feature(slice_patterns)] +#![feature(core)] // used for a lot of low-level stuff +#![feature(unsafe_no_drop_flag)] // crucial so that PyObject<'p> is binary compatible with *mut ffi::PyObject +#![feature(filling_drop)] // necessary to avoid segfault with unsafe_no_drop_flag +#![feature(optin_builtin_traits)] // for opting out of Sync/Send +#![feature(slice_patterns)] // for tuple_conversion macros +#![feature(utf8_error)] // for translating Utf8Error to python exception #![allow(unused_imports, dead_code, unused_variables)] -extern crate core; // NonZero is not exposed in std? extern crate libc; extern crate python27_sys as ffi; pub use ffi::Py_ssize_t; diff --git a/src/objects/exc.rs b/src/objects/exc.rs index 0f8f8a30..30539bea 100644 --- a/src/objects/exc.rs +++ b/src/objects/exc.rs @@ -94,12 +94,8 @@ impl<'p> UnicodeDecodeError<'p> { } pub fn new_utf8(py: Python<'p>, input: &[u8], err: Utf8Error) -> PyResult<'p, UnicodeDecodeError<'p>> { - match err { - Utf8Error::InvalidByte(pos) => - UnicodeDecodeError::new(py, cstr!("utf-8"), input, pos .. pos+1, cstr!("invalid byte")), - Utf8Error::TooShort => - UnicodeDecodeError::new(py, cstr!("utf-8"), input, input.len() - 1 .. input.len(), cstr!("unexpected end of data")), - } + let pos = err.valid_up_to(); + UnicodeDecodeError::new(py, cstr!("utf-8"), input, pos .. input.len(), cstr!("invalid utf-8")) } } diff --git a/src/objects/object.rs b/src/objects/object.rs index 5644d129..504a2233 100644 --- a/src/objects/object.rs +++ b/src/objects/object.rs @@ -1,5 +1,4 @@ -use core::nonzero::NonZero; -use std::mem::{size_of, transmute}; +use std::mem::{size_of, transmute, POST_DROP_USIZE}; use libc; use ffi; use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, PythonObjectWithTypeObject, PythonObjectDowncastError, ToPythonPointer}; @@ -7,26 +6,28 @@ use objects::PyType; use err::{PyErr, PyResult}; #[unsafe_no_drop_flag] +#[repr(C)] pub struct PyObject<'p> { // PyObject<'p> owns one reference to the *PyObject // ptr is not null (except possibly due to #[unsafe_no_drop_flag]) - ptr: NonZero<*mut ffi::PyObject>, + ptr: *mut ffi::PyObject, py : Python<'p> } -#[unsafe_destructor] impl <'p> Drop for PyObject<'p> { #[inline] fn drop(&mut self) { - // TODO: change from Py_XDECREF to Py_DECREF when #[unsafe_no_drop_flag] disappears - unsafe { ffi::Py_XDECREF(*self.ptr); } + // TODO: remove if and change Py_XDECREF to Py_DECREF when #[unsafe_no_drop_flag] disappears + if self.ptr as usize != POST_DROP_USIZE { + unsafe { ffi::Py_XDECREF(self.ptr); } + } } } impl <'p> Clone for PyObject<'p> { #[inline] fn clone(&self) -> PyObject<'p> { - unsafe { ffi::Py_INCREF(*self.ptr) }; + unsafe { ffi::Py_INCREF(self.ptr) }; PyObject { ptr: self.ptr, py: self.py } } } @@ -80,12 +81,12 @@ impl <'p> PythonObjectWithTypeObject<'p> for PyObject<'p> { impl <'p> ToPythonPointer for PyObject<'p> { #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { - *self.ptr + self.ptr } #[inline] fn steal_ptr(self) -> *mut ffi::PyObject { - let ptr = *self.ptr; + let ptr = self.ptr; unsafe { ::std::mem::forget(self); } ptr } @@ -99,7 +100,7 @@ impl <'p> PyObject<'p> { #[inline] pub unsafe fn from_owned_ptr(py : Python<'p>, ptr : *mut ffi::PyObject) -> PyObject<'p> { debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0); - PyObject { py: py, ptr: NonZero::new(ptr) } + PyObject { py: py, ptr: ptr } } /// Creates a PyObject instance for the given FFI pointer. @@ -109,7 +110,7 @@ impl <'p> PyObject<'p> { pub unsafe fn from_borrowed_ptr(py : Python<'p>, ptr : *mut ffi::PyObject) -> PyObject<'p> { debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0); ffi::Py_INCREF(ptr); - PyObject { py: py, ptr: NonZero::new(ptr) } + PyObject { py: py, ptr: ptr } } /// Creates a PyObject instance for the given FFI pointer. diff --git a/src/python.rs b/src/python.rs index 5559fbab..461c13d1 100644 --- a/src/python.rs +++ b/src/python.rs @@ -18,7 +18,7 @@ impl !Sync for PythonInterpreterState {} /// For example, python constants like None have the type "&'p PyObject<'p>". /// You can imagine the GIL to be a giant "Mutex". This makes 'p the lifetime of the /// python state protected by that mutex. -#[derive(Copy)] +#[derive(Copy, Clone)] pub struct Python<'p>(PhantomData<&'p PythonInterpreterState>); // Trait for converting from Self to *mut ffi::PyObject