@@ -3,10 +3,7 @@ use crate::object::define_py_check;
33use crate :: pystate:: with_vm;
44use crate :: util:: FfiPtrExt ;
55use core:: ffi:: c_int;
6- use rustpython_vm:: AsObject ;
7- use rustpython_vm:: PyObjectRef ;
86use rustpython_vm:: builtins:: PyList ;
9- use rustpython_vm:: sliceable:: { SaturatedSlice , SliceableSequenceMutOp , SliceableSequenceOp } ;
107
118define_py_check ! ( fn PyList_Check , types. list_type) ;
129define_py_check ! ( exact fn PyList_CheckExact , types. list_type) ;
@@ -25,19 +22,16 @@ pub extern "C" fn PyList_New(size: isize) -> *mut PyObject {
2522pub unsafe extern "C" fn PyList_Size ( obj : * mut PyObject ) -> isize {
2623 with_vm ( |vm| {
2724 let list = unsafe { obj. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
28- Ok ( list. __len__ ( ) )
25+ Ok ( list. len ( ) )
2926 } )
3027}
3128
3229#[ unsafe( no_mangle) ]
3330pub unsafe extern "C" fn PyList_GetItemRef ( obj : * mut PyObject , index : isize ) -> * mut PyObject {
3431 with_vm ( |vm| {
3532 let list = unsafe { obj. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
36- index
37- . try_into ( )
38- . ok ( )
39- . and_then ( |index : usize | list. borrow_vec ( ) . get ( index) . map ( ToOwned :: to_owned) )
40- . ok_or_else ( || vm. new_index_error ( format ! ( "list index out of range: {index}" ) ) )
33+ // A negative index wraps past the end and is out of range.
34+ list. get_item ( index as usize , vm)
4135 } )
4236}
4337
@@ -50,25 +44,17 @@ pub unsafe extern "C" fn PyList_SetItem(
5044 with_vm ( |vm| {
5145 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
5246 let item = unsafe { item. assume_owned ( ) } ;
53- let index_error =
54- || vm. new_index_error ( format ! ( "list assignment index out of range: {index}" ) ) ;
55- if index < 0 {
56- return Err ( index_error ( ) ) ;
57- }
58-
59- let mut list_mut = list. borrow_vec_mut ( ) ;
60- match index - list_mut. len ( ) as isize {
61- ..0 => {
62- list_mut[ index as usize ] = item;
63- Ok ( ( ) )
64- }
47+ // A negative index wraps past the end and is out of range.
48+ let index = index as usize ;
49+ {
50+ let mut list_mut = list. borrow_vec_mut ( ) ;
6551 // This is somewhat a hack, we assume that we are populating a list right after PyList_New
66- 0 if list_mut. capacity ( ) > index as usize => {
52+ if index == list_mut. len ( ) && list_mut . capacity ( ) > index {
6753 list_mut. push ( item) ;
68- Ok ( ( ) )
54+ return Ok ( ( ) ) ;
6955 }
70- 0 .. => Err ( index_error ( ) ) ,
7156 }
57+ list. set_item ( index, item, vm)
7258 } )
7359}
7460
@@ -77,7 +63,7 @@ pub unsafe extern "C" fn PyList_Append(list: *mut PyObject, item: *mut PyObject)
7763 with_vm ( |vm| {
7864 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
7965 let item = unsafe { item. assume_borrowed ( ) } . to_owned ( ) ;
80- list. borrow_vec_mut ( ) . push ( item) ;
66+ list. append ( item) ;
8167 Ok ( ( ) )
8268 } )
8369}
@@ -91,14 +77,7 @@ pub unsafe extern "C" fn PyList_Insert(
9177 with_vm ( |vm| {
9278 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
9379 let item = unsafe { item. assume_borrowed ( ) } . to_owned ( ) ;
94- let mut vec = list. borrow_vec_mut ( ) ;
95- let index = if index < 0 {
96- index + vec. len ( ) as isize
97- } else {
98- index
99- }
100- . clamp ( 0 , vec. len ( ) as isize ) as usize ;
101- vec. insert ( index, item) ;
80+ list. insert ( index, item) ;
10281 Ok ( ( ) )
10382 } )
10483}
@@ -107,7 +86,7 @@ pub unsafe extern "C" fn PyList_Insert(
10786pub unsafe extern "C" fn PyList_Reverse ( list : * mut PyObject ) -> c_int {
10887 with_vm ( |vm| {
10988 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
110- list. borrow_vec_mut ( ) . reverse ( ) ;
89+ list. reverse ( ) ;
11190 Ok ( ( ) )
11291 } )
11392}
@@ -116,7 +95,7 @@ pub unsafe extern "C" fn PyList_Reverse(list: *mut PyObject) -> c_int {
11695pub unsafe extern "C" fn PyList_AsTuple ( list : * mut PyObject ) -> * mut PyObject {
11796 with_vm ( |vm| {
11897 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
119- Ok ( vm . ctx . new_tuple ( list. borrow_vec ( ) . to_vec ( ) ) )
98+ Ok ( list. to_tuple ( vm ) )
12099 } )
121100}
122101
@@ -128,9 +107,7 @@ pub unsafe extern "C" fn PyList_GetSlice(
128107) -> * mut PyObject {
129108 with_vm ( |vm| {
130109 let list = unsafe { list. assume_borrowed_and_cast :: < 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) )
110+ Ok ( list. get_slice ( low, high, vm) )
134111 } )
135112}
136113
@@ -143,31 +120,26 @@ pub unsafe extern "C" fn PyList_SetSlice(
143120) -> c_int {
144121 with_vm ( |vm| {
145122 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
146- let slice = SaturatedSlice :: from_parts ( low, high, 1 ) ;
147- let mut vec = list. borrow_vec_mut ( ) ;
148-
149123 let Some ( itemlist) = ( unsafe { itemlist. assume_borrowed_or_opt ( ) } ) else {
150- vec . delitem_by_slice ( vm , slice ) ?;
124+ list . del_slice ( low , high , vm ) ?;
151125 return Ok ( ( ) ) ;
152126 } ;
153-
154- let items: Vec < PyObjectRef > = itemlist. try_to_value ( vm) ?;
155- vec. setitem_by_slice ( vm, slice, & items)
127+ list. set_slice ( low, high, itemlist, vm)
156128 } )
157129}
158130
159131#[ unsafe( no_mangle) ]
160132pub unsafe extern "C" fn PyList_Sort ( list : * mut PyObject ) -> c_int {
161133 with_vm ( |vm| {
162134 let list = unsafe { list. assume_borrowed_and_cast :: < PyList > ( vm) } ?;
163- vm. call_method ( list. as_object ( ) , "sort" , ( ) ) ?;
164- Ok ( ( ) )
135+ list. sort_default ( vm)
165136 } )
166137}
167138
168139#[ cfg( test) ]
169140mod tests {
170141 use pyo3:: exceptions:: PyIndexError ;
142+ use pyo3:: ffi;
171143 use pyo3:: prelude:: * ;
172144 use pyo3:: types:: { PyList , PyListMethods } ;
173145
@@ -288,4 +260,39 @@ mod tests {
288260 assert_eq ! ( list. get_item( 2 ) . unwrap( ) . extract:: <u32 >( ) . unwrap( ) , 3 ) ;
289261 } )
290262 }
263+
264+ #[ test]
265+ fn list_del_slice ( ) {
266+ Python :: attach ( |py| {
267+ let list = PyList :: new ( py, [ 1 , 2 , 3 , 4 ] ) . unwrap ( ) ;
268+ list. del_slice ( 1 , 3 ) . unwrap ( ) ;
269+ assert_eq ! ( list. extract:: <Vec <u32 >>( ) . unwrap( ) , [ 1 , 4 ] ) ;
270+ } )
271+ }
272+
273+ #[ test]
274+ fn list_negative_indices ( ) {
275+ Python :: attach ( |py| unsafe {
276+ let list = PyList :: new ( py, [ 1 , 2 , 3 , 4 ] ) . unwrap ( ) ;
277+
278+ assert ! ( ffi:: PyList_GetItemRef ( list. as_ptr( ) , -1 ) . is_null( ) ) ;
279+ assert ! ( PyErr :: take( py) . unwrap( ) . is_instance_of:: <PyIndexError >( py) ) ;
280+
281+ let slice = Bound :: from_owned_ptr ( py, ffi:: PyList_GetSlice ( list. as_ptr ( ) , -1 , 2 ) ) ;
282+ assert_eq ! ( slice. extract:: <Vec <u32 >>( ) . unwrap( ) , [ 1 , 2 ] ) ;
283+
284+ let repl = PyList :: new ( py, [ 9 ] ) . unwrap ( ) ;
285+ assert_eq ! ( ffi:: PyList_SetSlice ( list. as_ptr( ) , -1 , 1 , repl. as_ptr( ) ) , 0 ) ;
286+ assert_eq ! ( list. extract:: <Vec <u32 >>( ) . unwrap( ) , [ 9 , 2 , 3 , 4 ] ) ;
287+ } )
288+ }
289+
290+ #[ test]
291+ fn list_set_slice_self ( ) {
292+ Python :: attach ( |py| {
293+ let list = PyList :: new ( py, [ 1 , 2 ] ) . unwrap ( ) ;
294+ list. set_slice ( 2 , 2 , list. as_any ( ) ) . unwrap ( ) ;
295+ assert_eq ! ( list. extract:: <Vec <u32 >>( ) . unwrap( ) , [ 1 , 2 , 1 , 2 ] ) ;
296+ } )
297+ }
291298}
0 commit comments