@@ -42,7 +42,7 @@ impl PyTuple {
42
42
pub fn len ( & self ) -> usize {
43
43
unsafe {
44
44
// non-negative Py_ssize_t should always fit into Rust uint
45
- ffi:: PyTuple_GET_SIZE ( self . as_ptr ( ) ) as usize
45
+ ffi:: PyTuple_Size ( self . as_ptr ( ) ) as usize
46
46
}
47
47
}
48
48
@@ -62,8 +62,7 @@ impl PyTuple {
62
62
/// Takes a slice of the tuple from `low` to the end and returns it as a new tuple.
63
63
pub fn split_from ( & self , low : isize ) -> & PyTuple {
64
64
unsafe {
65
- let ptr =
66
- ffi:: PyTuple_GetSlice ( self . as_ptr ( ) , low, ffi:: PyTuple_GET_SIZE ( self . as_ptr ( ) ) ) ;
65
+ let ptr = ffi:: PyTuple_GetSlice ( self . as_ptr ( ) , low, self . len ( ) as Py_ssize_t ) ;
67
66
self . py ( ) . from_owned_ptr ( ptr)
68
67
}
69
68
}
@@ -75,11 +74,14 @@ impl PyTuple {
75
74
assert ! ( index < self . len( ) ) ;
76
75
unsafe {
77
76
self . py ( )
78
- . from_borrowed_ptr ( ffi:: PyTuple_GET_ITEM ( self . as_ptr ( ) , index as Py_ssize_t ) )
77
+ . from_borrowed_ptr ( ffi:: PyTuple_GetItem ( self . as_ptr ( ) , index as Py_ssize_t ) )
79
78
}
80
79
}
81
80
82
81
/// Returns `self` as a slice of objects.
82
+ ///
83
+ /// Not available when compiled with Py_LIMITED_API.
84
+ #[ cfg( not( Py_LIMITED_API ) ) ]
83
85
pub fn as_slice ( & self ) -> & [ & PyAny ] {
84
86
// This is safe because &PyAny has the same memory layout as *mut ffi::PyObject,
85
87
// and because tuples are immutable.
@@ -93,25 +95,27 @@ impl PyTuple {
93
95
/// Returns an iterator over the tuple items.
94
96
pub fn iter ( & self ) -> PyTupleIterator {
95
97
PyTupleIterator {
96
- slice : self . as_slice ( ) ,
98
+ tuple : self ,
97
99
index : 0 ,
100
+ length : self . len ( ) ,
98
101
}
99
102
}
100
103
}
101
104
102
105
/// Used by `PyTuple::iter()`.
103
106
pub struct PyTupleIterator < ' a > {
104
- slice : & ' a [ & ' a PyAny ] ,
107
+ tuple : & ' a PyTuple ,
105
108
index : usize ,
109
+ length : usize ,
106
110
}
107
111
108
112
impl < ' a > Iterator for PyTupleIterator < ' a > {
109
113
type Item = & ' a PyAny ;
110
114
111
115
#[ inline]
112
116
fn next ( & mut self ) -> Option < & ' a PyAny > {
113
- if self . index < self . slice . len ( ) {
114
- let item = self . slice [ self . index ] ;
117
+ if self . index < self . length {
118
+ let item = self . tuple . get_item ( self . index ) ;
115
119
self . index += 1 ;
116
120
Some ( item)
117
121
} else {
@@ -172,10 +176,9 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
172
176
fn extract( obj: & ' s PyAny ) -> PyResult <Self >
173
177
{
174
178
let t = <PyTuple as PyTryFrom >:: try_from( obj) ?;
175
- let slice = t. as_slice( ) ;
176
179
if t. len( ) == $length {
177
180
Ok ( (
178
- $( slice [ $n ] . extract:: <$T>( ) ?, ) +
181
+ $( t . get_item ( $n ) . extract:: <$T>( ) ?, ) +
179
182
) )
180
183
} else {
181
184
Err ( wrong_tuple_length( t, $length) )
@@ -296,4 +299,19 @@ mod test {
296
299
assert_eq ! ( i + 1 , item. extract( ) . unwrap( ) ) ;
297
300
}
298
301
}
302
+
303
+ #[ test]
304
+ #[ cfg( not( Py_LIMITED_API ) ) ]
305
+ fn test_as_slice ( ) {
306
+ let gil = Python :: acquire_gil ( ) ;
307
+ let py = gil. python ( ) ;
308
+ let ob = ( 1 , 2 , 3 ) . to_object ( py) ;
309
+ let tuple = <PyTuple as PyTryFrom >:: try_from ( ob. as_ref ( py) ) . unwrap ( ) ;
310
+
311
+ let slice = tuple. as_slice ( ) ;
312
+ assert_eq ! ( 3 , slice. len( ) ) ;
313
+ assert_eq ! ( 1 , slice[ 0 ] . extract( ) . unwrap( ) ) ;
314
+ assert_eq ! ( 2 , slice[ 1 ] . extract( ) . unwrap( ) ) ;
315
+ assert_eq ! ( 3 , slice[ 2 ] . extract( ) . unwrap( ) ) ;
316
+ }
299
317
}
0 commit comments