1use super::object::PyObject;
20use crate::conversion::{FromPyObject, ToPyObject};
21use crate::err::{self, PyErr, PyResult};
22use crate::ffi::{self, Py_ssize_t};
23use crate::python::{PyClone, PyDrop, Python, PythonObject, ToPythonPointer};
24
25pub struct PyList(PyObject);
27
28pyobject_newtype!(PyList, PyList_Check, PyList_Type);
29
30impl PyList {
31 pub fn new(py: Python, elements: &[PyObject]) -> PyList {
33 unsafe {
34 let ptr = ffi::PyList_New(elements.len() as Py_ssize_t);
35 let t = err::result_from_owned_ptr(py, ptr)
36 .unwrap()
37 .unchecked_cast_into::<PyList>();
38 for (i, e) in elements.iter().enumerate() {
39 ffi::PyList_SetItem(ptr, i as Py_ssize_t, e.steal_ptr(py));
40 }
41 t
42 }
43 }
44
45 #[inline]
47 pub fn len(&self, _py: Python) -> usize {
48 unsafe { ffi::PyList_Size(self.0.as_ptr()) as usize }
50 }
51
52 pub fn get_item(&self, py: Python, index: usize) -> PyObject {
56 assert!(index < self.len(py));
58 unsafe {
59 PyObject::from_borrowed_ptr(
60 py,
61 ffi::PyList_GetItem(self.0.as_ptr(), index as Py_ssize_t),
62 )
63 }
64 }
65
66 pub fn set_item(&self, _py: Python, index: usize, item: PyObject) {
70 let r =
71 unsafe { ffi::PyList_SetItem(self.0.as_ptr(), index as Py_ssize_t, item.steal_ptr()) };
72 assert!(r == 0);
73 }
74
75 pub fn insert(&self, _py: Python, index: usize, item: PyObject) {
79 let r = unsafe { ffi::PyList_Insert(self.0.as_ptr(), index as Py_ssize_t, item.as_ptr()) };
80 assert!(r == 0);
81 }
82
83 #[deprecated(since = "0.3.1", note = "use list.insert() instead")]
85 #[doc(hidden)]
86 pub fn insert_item(&self, py: Python, index: usize, item: PyObject) {
87 self.insert(py, index, item);
88 }
89
90 pub fn append(&self, _py: Python, item: PyObject) {
92 unsafe { ffi::PyList_Append(self.0.as_ptr(), item.as_ptr()) };
93 }
94
95 #[inline]
96 pub fn iter<'a, 'p>(&'a self, py: Python<'p>) -> PyListIterator<'a, 'p> {
97 PyListIterator {
98 py,
99 list: self,
100 index: 0,
101 }
102 }
103}
104
105pub struct PyListIterator<'a, 'p> {
107 py: Python<'p>,
108 list: &'a PyList,
109 index: usize,
110}
111
112impl<'a, 'p> Iterator for PyListIterator<'a, 'p> {
113 type Item = PyObject;
114
115 #[inline]
116 fn next(&mut self) -> Option<PyObject> {
117 if self.index < self.list.len(self.py) {
118 let item = self.list.get_item(self.py, self.index);
119 self.index += 1;
120 Some(item)
121 } else {
122 None
123 }
124 }
125
126 }
129
130impl<T> ToPyObject for [T]
136where
137 T: ToPyObject,
138{
139 type ObjectType = PyList;
140
141 fn to_py_object(&self, py: Python) -> PyList {
142 unsafe {
143 let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
144 let t = err::cast_from_owned_ptr_or_panic(py, ptr);
145 for (i, e) in self.iter().enumerate() {
146 let obj = e.to_py_object(py).into_object();
147 ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj.steal_ptr());
148 }
149 t
150 }
151 }
152}
153
154impl<T> ToPyObject for Vec<T>
160where
161 T: ToPyObject,
162{
163 type ObjectType = PyList;
164
165 fn to_py_object(&self, py: Python) -> PyList {
166 self.as_slice().to_py_object(py)
167 }
168
169 fn into_py_object(self, py: Python) -> PyList {
170 unsafe {
171 let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
172 let t = err::cast_from_owned_ptr_or_panic(py, ptr);
173 for (i, e) in self.into_iter().enumerate() {
174 let obj = e.into_py_object(py).into_object();
175 ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj.steal_ptr());
176 }
177 t
178 }
179 }
180}
181
182#[cfg(test)]
183mod test {
184 use crate::conversion::ToPyObject;
185 use crate::objects::PyList;
186 use crate::python::{Python, PythonObject};
187
188 #[test]
189 fn test_len() {
190 let gil = Python::acquire_gil();
191 let py = gil.python();
192 let v = vec![1, 2, 3, 4];
193 let list = v.to_py_object(py);
194 assert_eq!(4, list.len(py));
195 }
196
197 #[test]
198 fn test_get_item() {
199 let gil = Python::acquire_gil();
200 let py = gil.python();
201 let v = vec![2, 3, 5, 7];
202 let list = v.to_py_object(py);
203 assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
204 assert_eq!(3, list.get_item(py, 1).extract::<i32>(py).unwrap());
205 assert_eq!(5, list.get_item(py, 2).extract::<i32>(py).unwrap());
206 assert_eq!(7, list.get_item(py, 3).extract::<i32>(py).unwrap());
207 }
208
209 #[test]
210 fn test_set_item() {
211 let gil = Python::acquire_gil();
212 let py = gil.python();
213 let v = vec![2, 3, 5, 7];
214 let list = v.to_py_object(py);
215 let val = 42i32.to_py_object(py).into_object();
216 assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
217 list.set_item(py, 0, val);
218 assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
219 }
220
221 #[test]
222 fn test_insert() {
223 let gil = Python::acquire_gil();
224 let py = gil.python();
225 let v = vec![2, 3, 5, 7];
226 let list = v.to_py_object(py);
227 let val = 42i32.to_py_object(py).into_object();
228 assert_eq!(4, list.len(py));
229 assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
230 list.insert(py, 0, val);
231 assert_eq!(5, list.len(py));
232 assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
233 assert_eq!(2, list.get_item(py, 1).extract::<i32>(py).unwrap());
234 }
235
236 #[test]
237 fn test_append() {
238 let gil = Python::acquire_gil();
239 let py = gil.python();
240 let v = vec![2, 3, 5, 7];
241 let list = v.to_py_object(py);
242 let val = 42i32.to_py_object(py).into_object();
243 assert_eq!(4, list.len(py));
244 list.append(py, val);
245 assert_eq!(5, list.len(py));
246 assert_eq!(42, list.get_item(py, 4).extract::<i32>(py).unwrap());
247 }
248
249 #[test]
250 fn test_iter() {
251 let gil = Python::acquire_gil();
252 let py = gil.python();
253 let v = vec![2, 3, 5, 7];
254 let list = v.to_py_object(py);
255 let mut idx = 0;
256 for el in list.iter(py) {
257 assert_eq!(v[idx], el.extract::<i32>(py).unwrap());
258 idx += 1;
259 }
260 assert_eq!(idx, v.len());
261 }
262
263 #[test]
264 fn test_extract() {
265 let gil = Python::acquire_gil();
266 let py = gil.python();
267 let v = vec![2, 3, 5, 7];
268 let list = v.to_py_object(py);
269 let v2 = list.into_object().extract::<Vec<i32>>(py).unwrap();
270 assert_eq!(v, v2);
271 }
272}