pyo2 0.1.2

A lightweight method to call Rust code from Python
Documentation
use std::ops::{Deref, Index};
use std::ops::{DerefMut, IndexMut};
use std::slice::{self, SliceIndex};

/// A Python list-like type passed to Rust.
///
/// # Examples
///
/// In Python:
///
/// ```python
/// dll = RustDLL('./libtest.so')
/// print(dll.func([1, 2, 3, 4, 5]))
/// ```
///
/// In Rust:
///
/// ```
/// fn func(vec: &PyVec<i64>) -> i64 {
///     vec.iter().sum()
/// }
/// ```
///
/// Output: `15`
#[repr(C)]
pub struct PyVec<T> {
    ptr: *mut T,
    len: u32,
}

impl<T> PyVec<T> {
    /// Returns the internal data as a read-only raw pointer.
    pub fn as_ptr(&self) -> *const T {
        self.ptr as *const T
    }

    /// Returns the internal data as a mutable raw pointer. Mutating this data
    /// will (in most cases) also mutate the data in Python, with the exception
    /// of the Python `str` type.
    pub fn as_mut_ptr(&mut self) -> *mut T {
        self.ptr
    }

    /// Returns the length of the data in the number of elements.
    pub fn len(&self) -> usize {
        self.len as usize
    }

    /// Copies the data into a new `Vec`.
    pub fn to_vec(&self) -> Vec<T>
    where
        T: Clone,
    {
        (&**self).to_vec()
    }
}

impl<T> Deref for PyVec<T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        // SAFETY: We trust the Python side to pass us a valid pointer and len.
        unsafe { slice::from_raw_parts(self.ptr, self.len as usize) }
    }
}

impl<T> DerefMut for PyVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        // SAFETY: We trust the Python side to pass us a valid pointer and len.
        unsafe { slice::from_raw_parts_mut(self.ptr, self.len as usize) }
    }
}

impl<T, I: SliceIndex<[T]>> Index<I> for PyVec<T> {
    type Output = I::Output;

    fn index(&self, index: I) -> &Self::Output {
        Index::index(&**self, index)
    }
}

impl<T, I: SliceIndex<[T]>> IndexMut<I> for PyVec<T> {
    fn index_mut(&mut self, index: I) -> &mut Self::Output {
        IndexMut::index_mut(&mut **self, index)
    }
}

/// A Python `str` or `bytes` passed to Rust.
pub type PyStr = PyVec<u8>;

impl PyStr {
    /// Converts `self` into a string slice.
    ///
    /// This method checks if the data is valid UTF-8. See [`as_str_unchecked`].
    ///
    /// [`as_str_unchecked`]: PyStr::as_str_unchecked
    pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> {
        std::str::from_utf8(&*self)
    }

    /// Converts `self` into a string slice without checking if the data is
    /// valid UTF-8.
    ///
    /// # Safety
    ///
    /// This method is unsafe because it doesn't check the validity of the
    /// data as UTF-8. For a safe alternative, see [`as_str`].
    ///
    /// [`as_str`]: PyStr::as_str
    pub unsafe fn as_str_unchecked(&self) -> &str {
        std::str::from_utf8_unchecked(&*self)
    }
}