use crate::err::{PyErr, PyResult};
use crate::ffi::{self, Py_ssize_t};
use crate::instance::PyNativeType;
use crate::{AsPyPointer, PyAny, PyObject, Python, ToPyObject};
use std::os::raw::c_long;
#[repr(transparent)]
pub struct PySlice(PyAny);
pyobject_native_type!(
PySlice,
ffi::PySliceObject,
ffi::PySlice_Type,
#checkfunction=ffi::PySlice_Check
);
pub struct PySliceIndices {
pub start: isize,
pub stop: isize,
pub step: isize,
pub slicelength: isize,
}
impl PySliceIndices {
pub fn new(start: isize, stop: isize, step: isize) -> PySliceIndices {
PySliceIndices {
start,
stop,
step,
slicelength: 0,
}
}
}
impl PySlice {
pub fn new(py: Python, start: isize, stop: isize, step: isize) -> &PySlice {
unsafe {
let ptr = ffi::PySlice_New(
ffi::PyLong_FromLong(start as c_long),
ffi::PyLong_FromLong(stop as c_long),
ffi::PyLong_FromLong(step as c_long),
);
py.from_owned_ptr(ptr)
}
}
#[inline]
pub fn indices(&self, length: c_long) -> PyResult<PySliceIndices> {
unsafe {
let slicelength: isize = 0;
let start: isize = 0;
let stop: isize = 0;
let step: isize = 0;
let r = ffi::PySlice_GetIndicesEx(
self.as_ptr(),
length as Py_ssize_t,
&start as *const _ as *mut _,
&stop as *const _ as *mut _,
&step as *const _ as *mut _,
&slicelength as *const _ as *mut _,
);
if r == 0 {
Ok(PySliceIndices {
start,
stop,
step,
slicelength,
})
} else {
Err(PyErr::fetch(self.py()))
}
}
}
}
impl ToPyObject for PySliceIndices {
fn to_object(&self, py: Python) -> PyObject {
PySlice::new(py, self.start, self.stop, self.step).into()
}
}