Skip to content

Commit 5e5e96d

Browse files
committed
Support arbitrary arrays
1 parent 494ed63 commit 5e5e96d

File tree

4 files changed

+86
-1
lines changed

4 files changed

+86
-1
lines changed

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#![cfg_attr(feature = "nightly", feature(specialization))]
1+
#![cfg_attr(feature = "nightly", allow(incomplete_features))]
2+
#![cfg_attr(feature = "nightly", feature(min_const_generics, specialization))]
23
#![allow(clippy::missing_safety_doc)] // FIXME (#698)
34

45
//! Rust bindings to the Python interpreter.

src/types/list.rs

+12
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ where
178178
}
179179
}
180180

181+
#[cfg(feature = "nightly")]
182+
impl<T, const N: usize> IntoPy<PyObject> for [T; N]
183+
where
184+
T: ToPyObject,
185+
{
186+
fn into_py(self, py: Python) -> PyObject {
187+
self.as_ref().to_object(py)
188+
}
189+
}
190+
191+
#[cfg(not(feature = "nightly"))]
181192
macro_rules! array_impls {
182193
($($N:expr),+) => {
183194
$(
@@ -193,6 +204,7 @@ macro_rules! array_impls {
193204
}
194205
}
195206

207+
#[cfg(not(feature = "nightly"))]
196208
array_impls!(
197209
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
198210
26, 27, 28, 29, 30, 31, 32

src/types/mod.rs

+37
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,40 @@ mod slice;
235235
mod string;
236236
mod tuple;
237237
mod typeobject;
238+
239+
#[cfg(feature = "nightly")]
240+
struct ArrayGuard<T, const N: usize> {
241+
dst: *mut T,
242+
initialized: usize,
243+
}
244+
245+
#[cfg(feature = "nightly")]
246+
impl<T, const N: usize> Drop for ArrayGuard<T, N> {
247+
fn drop(&mut self) {
248+
debug_assert!(self.initialized <= N);
249+
let initialized_part = core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
250+
unsafe {
251+
core::ptr::drop_in_place(initialized_part);
252+
}
253+
}
254+
}
255+
256+
#[cfg(feature = "nightly")]
257+
fn create_array<F, T, const N: usize>(mut cb: F) -> [T; N]
258+
where
259+
F: FnMut(usize) -> T,
260+
{
261+
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
262+
let mut guard: ArrayGuard<T, N> = ArrayGuard {
263+
dst: array.as_mut_ptr() as _,
264+
initialized: 0,
265+
};
266+
unsafe {
267+
for (idx, value_ptr) in (&mut *array.as_mut_ptr()).iter_mut().enumerate() {
268+
core::ptr::write(value_ptr, cb(idx));
269+
guard.initialized += 1;
270+
}
271+
core::mem::forget(guard);
272+
array.assume_init()
273+
}
274+
}

src/types/sequence.rs

+35
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,40 @@ impl PySequence {
257257
}
258258
}
259259

260+
#[cfg(feature = "nightly")]
261+
impl<'a, T, const N: usize> FromPyObject<'a> for [T; N]
262+
where
263+
T: Copy + Default + FromPyObject<'a>,
264+
{
265+
default fn extract(obj: &'a PyAny) -> PyResult<Self> {
266+
let mut array = crate::types::create_array(|_| T::default());
267+
extract_sequence_into_slice(obj, &mut array)?;
268+
Ok(array)
269+
}
270+
}
271+
272+
#[cfg(feature = "nightly")]
273+
impl<'source, T, const N: usize> FromPyObject<'source> for [T; N]
274+
where
275+
for<'a> T: Default + FromPyObject<'a> + crate::buffer::Element,
276+
{
277+
fn extract(obj: &'source PyAny) -> PyResult<Self> {
278+
let mut array = crate::types::create_array(|_| T::default());
279+
// first try buffer protocol
280+
if let Ok(buf) = crate::buffer::PyBuffer::get(obj) {
281+
if buf.dimensions() == 1 && buf.copy_to_slice(obj.py(), &mut array).is_ok() {
282+
buf.release(obj.py());
283+
return Ok(array);
284+
}
285+
buf.release(obj.py());
286+
}
287+
// fall back to sequence protocol
288+
extract_sequence_into_slice(obj, &mut array)?;
289+
Ok(array)
290+
}
291+
}
292+
293+
#[cfg(not(feature = "nightly"))]
260294
macro_rules! array_impls {
261295
($($N:expr),+) => {
262296
$(
@@ -303,6 +337,7 @@ macro_rules! array_impls {
303337
}
304338
}
305339

340+
#[cfg(not(feature = "nightly"))]
306341
array_impls!(
307342
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
308343
26, 27, 28, 29, 30, 31, 32

0 commit comments

Comments
 (0)