Skip to content

Commit 073cd03

Browse files
Add more list functions to the c-api
1 parent 51c97b9 commit 073cd03

1 file changed

Lines changed: 115 additions & 10 deletions

File tree

crates/capi/src/listobject.rs

Lines changed: 115 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ use crate::object::define_py_check;
33
use crate::pystate::with_vm;
44
use core::ffi::c_int;
55
use core::ptr::NonNull;
6+
use rustpython_vm::AsObject;
67
use rustpython_vm::PyObjectRef;
78
use rustpython_vm::builtins::PyList;
9+
use rustpython_vm::sliceable::{SaturatedSlice, SliceableSequenceMutOp, SliceableSequenceOp};
810

911
define_py_check!(fn PyList_Check, types.list_type);
1012
define_py_check!(exact fn PyList_CheckExact, types.list_type);
@@ -110,16 +112,69 @@ pub unsafe extern "C" fn PyList_Reverse(list: *mut PyObject) -> c_int {
110112
})
111113
}
112114

115+
#[unsafe(no_mangle)]
116+
pub unsafe extern "C" fn PyList_AsTuple(list: *mut PyObject) -> *mut PyObject {
117+
with_vm(|vm| {
118+
let list = unsafe { &*list }.try_downcast_ref::<PyList>(vm)?;
119+
Ok(vm.ctx.new_tuple(list.borrow_vec().to_vec()))
120+
})
121+
}
122+
123+
#[unsafe(no_mangle)]
124+
pub unsafe extern "C" fn PyList_GetSlice(
125+
list: *mut PyObject,
126+
low: isize,
127+
high: isize,
128+
) -> *mut PyObject {
129+
with_vm(|vm| {
130+
let list = unsafe { &*list }.try_downcast_ref::<PyList>(vm)?;
131+
let vec = list.borrow_vec();
132+
let sliced = vec.getitem_by_slice(vm, SaturatedSlice::from_parts(low, high, 1))?;
133+
Ok(vm.ctx.new_list(sliced))
134+
})
135+
}
136+
137+
#[unsafe(no_mangle)]
138+
pub unsafe extern "C" fn PyList_SetSlice(
139+
list: *mut PyObject,
140+
low: isize,
141+
high: isize,
142+
itemlist: *mut PyObject,
143+
) -> c_int {
144+
with_vm(|vm| {
145+
let list = unsafe { &*list }.try_downcast_ref::<PyList>(vm)?;
146+
let slice = SaturatedSlice::from_parts(low, high, 1);
147+
let mut vec = list.borrow_vec_mut();
148+
149+
if itemlist.is_null() {
150+
vec.delitem_by_slice(vm, slice)?;
151+
return Ok(());
152+
}
153+
154+
let items: Vec<PyObjectRef> = unsafe { &*itemlist }.try_to_value(vm)?;
155+
vec.setitem_by_slice(vm, slice, &items)
156+
})
157+
}
158+
159+
#[unsafe(no_mangle)]
160+
pub unsafe extern "C" fn PyList_Sort(list: *mut PyObject) -> c_int {
161+
with_vm(|vm| {
162+
let list = unsafe { &*list }.try_downcast_ref::<PyList>(vm)?;
163+
vm.call_method(list.as_object(), "sort", ())?;
164+
Ok(())
165+
})
166+
}
167+
113168
#[cfg(false)]
114169
mod tests {
115170
use pyo3::exceptions::PyIndexError;
116171
use pyo3::prelude::*;
117-
use pyo3::types::PyList;
172+
use pyo3::types::{PyList, PyListMethods};
118173

119174
#[test]
120-
fn test_create_list() {
175+
fn create_list() {
121176
Python::attach(|py| {
122-
let list = PyList::new(py, &[1, 2, 3]).unwrap();
177+
let list = PyList::new(py, [1, 2, 3]).unwrap();
123178
assert_eq!(list.len(), 3);
124179
assert_eq!(list.get_item(0).unwrap().extract::<u32>().unwrap(), 1);
125180
assert_eq!(list.get_item(1).unwrap().extract::<u32>().unwrap(), 2);
@@ -129,9 +184,9 @@ mod tests {
129184
}
130185

131186
#[test]
132-
fn test_replace_item_in_list() {
187+
fn replace_item_in_list() {
133188
Python::attach(|py| {
134-
let list = PyList::new(py, &[1]).unwrap();
189+
let list = PyList::new(py, [1]).unwrap();
135190
assert_eq!(list.len(), 1);
136191
list.set_item(0, 2).unwrap();
137192
assert_eq!(list.len(), 1);
@@ -140,7 +195,7 @@ mod tests {
140195
}
141196

142197
#[test]
143-
fn test_set_item_out_of_range() {
198+
fn set_item_out_of_range() {
144199
Python::attach(|py| {
145200
let list = PyList::empty(py);
146201
assert!(
@@ -152,7 +207,7 @@ mod tests {
152207
}
153208

154209
#[test]
155-
fn test_list_append() {
210+
fn list_append() {
156211
Python::attach(|py| {
157212
let list = PyList::empty(py);
158213
assert_eq!(list.len(), 0);
@@ -163,7 +218,7 @@ mod tests {
163218
}
164219

165220
#[test]
166-
fn test_list_insert() {
221+
fn list_insert() {
167222
Python::attach(|py| {
168223
let list = PyList::empty(py);
169224
assert_eq!(list.len(), 0);
@@ -175,12 +230,62 @@ mod tests {
175230
}
176231

177232
#[test]
178-
fn test_list_reverse() {
233+
fn list_reverse() {
179234
Python::attach(|py| {
180-
let list = PyList::new(py, &[1, 2, 3]).unwrap();
235+
let list = PyList::new(py, [1, 2, 3]).unwrap();
181236
list.reverse().unwrap();
182237
assert_eq!(list.get_item(0).unwrap().extract::<u32>().unwrap(), 3);
183238
assert_eq!(list.get_item(2).unwrap().extract::<u32>().unwrap(), 1);
184239
})
185240
}
241+
242+
#[test]
243+
fn list_as_tuple() {
244+
Python::attach(|py| {
245+
let list = PyList::new(py, [1, 2, 3]).unwrap();
246+
let tuple = list.to_tuple();
247+
assert_eq!(tuple.len(), 3);
248+
assert_eq!(tuple.get_item(0).unwrap().extract::<u32>().unwrap(), 1);
249+
250+
list.set_item(0, 9).unwrap();
251+
assert_eq!(tuple.get_item(0).unwrap().extract::<u32>().unwrap(), 1);
252+
})
253+
}
254+
255+
#[test]
256+
fn list_get_slice() {
257+
Python::attach(|py| {
258+
let list = PyList::new(py, [1, 2, 3, 4]).unwrap();
259+
let slice = list.get_slice(1, 10);
260+
assert_eq!(slice.len(), 3);
261+
assert_eq!(slice.get_item(0).unwrap().extract::<u32>().unwrap(), 2);
262+
assert_eq!(slice.get_item(2).unwrap().extract::<u32>().unwrap(), 4);
263+
})
264+
}
265+
266+
#[test]
267+
fn list_set_slice() {
268+
Python::attach(|py| {
269+
let list = PyList::new(py, [1, 2, 3, 4]).unwrap();
270+
let repl = PyList::new(py, [8, 9]).unwrap();
271+
list.set_slice(1, 3, repl.as_any()).unwrap();
272+
273+
assert_eq!(list.len(), 4);
274+
assert_eq!(list.get_item(0).unwrap().extract::<u32>().unwrap(), 1);
275+
assert_eq!(list.get_item(1).unwrap().extract::<u32>().unwrap(), 8);
276+
assert_eq!(list.get_item(2).unwrap().extract::<u32>().unwrap(), 9);
277+
assert_eq!(list.get_item(3).unwrap().extract::<u32>().unwrap(), 4);
278+
})
279+
}
280+
281+
#[test]
282+
fn list_sort() {
283+
Python::attach(|py| {
284+
let list = PyList::new(py, [3, 1, 2]).unwrap();
285+
list.sort().unwrap();
286+
assert_eq!(list.get_item(0).unwrap().extract::<u32>().unwrap(), 1);
287+
assert_eq!(list.get_item(1).unwrap().extract::<u32>().unwrap(), 2);
288+
assert_eq!(list.get_item(2).unwrap().extract::<u32>().unwrap(), 3);
289+
})
290+
}
186291
}

0 commit comments

Comments
 (0)