1use std::mem;
20
21use crate::buffer;
22use crate::conversion::{FromPyObject, ToPyObject};
23use crate::err;
24use crate::err::{result_cast_from_owned_ptr, result_from_owned_ptr, PyErr, PyResult};
25use crate::ffi;
26use crate::ffi::Py_ssize_t;
27use crate::objects::{PyIterator, PyList, PyObject, PyTuple};
28use crate::python::{PyClone, PyDrop, Python, PythonObject, ToPythonPointer};
29
30pub struct PySequence(PyObject);
32
33pyobject_newtype!(PySequence, PySequence_Check);
34
35impl PySequence {
36 #[inline]
38 pub fn len(&self, py: Python) -> PyResult<isize> {
39 let v = unsafe { ffi::PySequence_Size(self.0.as_ptr()) };
40 if v == -1 {
41 Err(PyErr::fetch(py))
42 } else {
43 Ok(v as isize)
44 }
45 }
46
47 #[inline]
49 pub fn concat(&self, py: Python, other: &PySequence) -> PyResult<PyObject> {
50 unsafe {
51 err::result_from_owned_ptr(py, ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))
52 }
53 }
54
55 #[inline]
59 pub fn repeat(&self, py: Python, count: isize) -> PyResult<PyObject> {
60 unsafe {
61 err::result_from_owned_ptr(
62 py,
63 ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t),
64 )
65 }
66 }
67
68 #[inline]
70 pub fn in_place_concat(&self, py: Python, other: &PySequence) -> PyResult<PyObject> {
71 unsafe {
72 result_from_owned_ptr(
73 py,
74 ffi::PySequence_InPlaceConcat(self.as_ptr(), other.as_ptr()),
75 )
76 }
77 }
78
79 #[inline]
83 pub fn in_place_repeat(&self, py: Python, count: isize) -> PyResult<PyObject> {
84 unsafe {
85 result_from_owned_ptr(
86 py,
87 ffi::PySequence_InPlaceRepeat(self.as_ptr(), count as Py_ssize_t),
88 )
89 }
90 }
91
92 #[inline]
94 pub fn get_item(&self, py: Python, index: isize) -> PyResult<PyObject> {
95 unsafe {
96 result_from_owned_ptr(
97 py,
98 ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t),
99 )
100 }
101 }
102
103 #[inline]
106 pub fn get_slice(&self, py: Python, begin: isize, end: isize) -> PyResult<PyObject> {
107 unsafe {
108 result_from_owned_ptr(
109 py,
110 ffi::PySequence_GetSlice(self.as_ptr(), begin as Py_ssize_t, end as Py_ssize_t),
111 )
112 }
113 }
114
115 #[inline]
118 pub fn set_item(&self, py: Python, i: isize, v: &PyObject) -> PyResult<()> {
119 unsafe {
120 err::error_on_minusone(
121 py,
122 ffi::PySequence_SetItem(self.as_ptr(), i as Py_ssize_t, v.as_ptr()),
123 )
124 }
125 }
126
127 #[inline]
130 pub fn del_item(&self, py: Python, i: isize) -> PyResult<()> {
131 unsafe {
132 err::error_on_minusone(py, ffi::PySequence_DelItem(self.as_ptr(), i as Py_ssize_t))
133 }
134 }
135
136 #[inline]
139 pub fn set_slice(&self, py: Python, i1: isize, i2: isize, v: &PyObject) -> PyResult<()> {
140 unsafe {
141 err::error_on_minusone(
142 py,
143 ffi::PySequence_SetSlice(
144 self.as_ptr(),
145 i1 as Py_ssize_t,
146 i2 as Py_ssize_t,
147 v.as_ptr(),
148 ),
149 )
150 }
151 }
152
153 #[inline]
156 pub fn del_slice(&self, py: Python, i1: isize, i2: isize) -> PyResult<()> {
157 unsafe {
158 err::error_on_minusone(
159 py,
160 ffi::PySequence_DelSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t),
161 )
162 }
163 }
164
165 #[inline]
168 pub fn count<V>(&self, py: Python, value: V) -> PyResult<usize>
169 where
170 V: ToPyObject,
171 {
172 let r = value.with_borrowed_ptr(py, |ptr| unsafe {
173 ffi::PySequence_Count(self.as_ptr(), ptr)
174 });
175 if r == -1 {
176 Err(PyErr::fetch(py))
177 } else {
178 Ok(r as usize)
179 }
180 }
181
182 #[inline]
184 pub fn contains<V>(&self, py: Python, value: V) -> PyResult<bool>
185 where
186 V: ToPyObject,
187 {
188 let r = value.with_borrowed_ptr(py, |ptr| unsafe {
189 ffi::PySequence_Contains(self.as_ptr(), ptr)
190 });
191 match r {
192 0 => Ok(false),
193 1 => Ok(true),
194 _ => Err(PyErr::fetch(py)),
195 }
196 }
197
198 #[inline]
201 pub fn index<V>(&self, py: Python, value: V) -> PyResult<usize>
202 where
203 V: ToPyObject,
204 {
205 let r = value.with_borrowed_ptr(py, |ptr| unsafe {
206 ffi::PySequence_Index(self.as_ptr(), ptr)
207 });
208 if r == -1 {
209 Err(PyErr::fetch(py))
210 } else {
211 Ok(r as usize)
212 }
213 }
214
215 #[inline]
217 pub fn list(&self, py: Python) -> PyResult<PyList> {
218 unsafe { result_cast_from_owned_ptr(py, ffi::PySequence_List(self.as_ptr())) }
219 }
220
221 #[inline]
223 pub fn tuple(&self, py: Python) -> PyResult<PyTuple> {
224 unsafe { result_cast_from_owned_ptr(py, ffi::PySequence_Tuple(self.as_ptr())) }
225 }
226
227 #[inline]
228 pub fn iter<'p>(&self, py: Python<'p>) -> PyResult<PyIterator<'p>> {
229 use crate::objectprotocol::ObjectProtocol;
230 self.as_object().iter(py)
231 }
232}
233
234#[cfg(not(feature = "nightly"))]
240impl<'s, T> FromPyObject<'s> for Vec<T>
241where
242 for<'a> T: FromPyObject<'a>,
243{
244 fn extract(py: Python, obj: &'s PyObject) -> PyResult<Self> {
245 extract_sequence(py, obj)
246 }
247}
248
249#[cfg(feature = "nightly")]
255impl<'s, T> FromPyObject<'s> for Vec<T>
256where
257 for<'a> T: FromPyObject<'a>,
258{
259 default fn extract(py: Python, obj: &'s PyObject) -> PyResult<Self> {
260 extract_sequence(py, obj)
261 }
262}
263
264#[cfg(feature = "nightly")]
271impl<'s, T> FromPyObject<'s> for Vec<T>
272where
273 for<'a> T: FromPyObject<'a> + buffer::Element + Copy,
274{
275 fn extract(py: Python, obj: &'s PyObject) -> PyResult<Self> {
276 extract_buffer_or_sequence(py, obj)
277 }
278}
279
280pub(crate) fn extract_buffer_or_sequence<T>(py: Python, obj: &PyObject) -> PyResult<Vec<T>>
281where
282 for<'a> T: FromPyObject<'a> + buffer::Element + Copy,
283{
284 if let Ok(buf) = buffer::PyBuffer::get(py, obj) {
286 if buf.dimensions() == 1 {
287 if let Ok(v) = buf.to_vec::<T>(py) {
288 buf.release_ref(py);
289 return Ok(v);
290 }
291 }
292 buf.release_ref(py);
293 }
294 extract_sequence(py, obj)
296}
297
298fn extract_sequence<T>(py: Python, obj: &PyObject) -> PyResult<Vec<T>>
299where
300 for<'a> T: FromPyObject<'a>,
301{
302 let seq = obj.cast_as::<PySequence>(py)?;
303 let mut v = Vec::new();
304 for item in seq.iter(py)? {
305 let item = item?;
306 v.push(T::extract(py, &item)?);
307 item.release_ref(py);
308 }
309 Ok(v)
310}
311
312#[cfg(test)]
313mod test {
314 use crate::conversion::ToPyObject;
315 use crate::objects::{PyIterator, PyList, PySequence, PyTuple};
316 use crate::python::{Python, PythonObject};
317
318 #[test]
319 fn test_numbers_are_not_sequences() {
320 let gil = Python::acquire_gil();
321 let py = gil.python();
322 let v = 42i32;
323 assert!(v
324 .to_py_object(py)
325 .into_object()
326 .cast_into::<PySequence>(py)
327 .is_err());
328 }
329
330 #[test]
331 fn test_strings_are_sequences() {
332 let gil = Python::acquire_gil();
333 let py = gil.python();
334 let v = "London Calling";
335 assert!(v
336 .to_py_object(py)
337 .into_object()
338 .cast_into::<PySequence>(py)
339 .is_ok());
340 }
341 #[test]
342 fn test_seq_empty() {
343 let gil = Python::acquire_gil();
344 let py = gil.python();
345 let v: Vec<i32> = vec![];
346 let seq = v
347 .to_py_object(py)
348 .into_object()
349 .cast_into::<PySequence>(py)
350 .unwrap();
351 assert_eq!(0, seq.len(py).unwrap());
352
353 let needle = 7i32.to_py_object(py).into_object();
354 assert_eq!(false, seq.contains(py, &needle).unwrap());
355 }
356
357 #[test]
358 fn test_seq_contains() {
359 let gil = Python::acquire_gil();
360 let py = gil.python();
361 let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
362 let seq = v
363 .to_py_object(py)
364 .into_object()
365 .cast_into::<PySequence>(py)
366 .unwrap();
367 assert_eq!(6, seq.len(py).unwrap());
368
369 let bad_needle = 7i32.to_py_object(py).into_object();
370 assert_eq!(false, seq.contains(py, &bad_needle).unwrap());
371
372 let good_needle = 8i32.to_py_object(py).into_object();
373 assert_eq!(true, seq.contains(py, &good_needle).unwrap());
374
375 let type_coerced_needle = 8f32.to_py_object(py).into_object();
376 assert_eq!(true, seq.contains(py, &type_coerced_needle).unwrap());
377 }
378
379 #[test]
380 fn test_seq_get_item() {
381 let gil = Python::acquire_gil();
382 let py = gil.python();
383 let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
384 let seq = v
385 .to_py_object(py)
386 .into_object()
387 .cast_into::<PySequence>(py)
388 .unwrap();
389 assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
390 assert_eq!(1, seq.get_item(py, 1).unwrap().extract::<i32>(py).unwrap());
391 assert_eq!(2, seq.get_item(py, 2).unwrap().extract::<i32>(py).unwrap());
392 assert_eq!(3, seq.get_item(py, 3).unwrap().extract::<i32>(py).unwrap());
393 assert_eq!(5, seq.get_item(py, 4).unwrap().extract::<i32>(py).unwrap());
394 assert_eq!(8, seq.get_item(py, 5).unwrap().extract::<i32>(py).unwrap());
395 assert_eq!(8, seq.get_item(py, -1).unwrap().extract::<i32>(py).unwrap());
396 assert_eq!(5, seq.get_item(py, -2).unwrap().extract::<i32>(py).unwrap());
397 assert_eq!(3, seq.get_item(py, -3).unwrap().extract::<i32>(py).unwrap());
398 assert_eq!(2, seq.get_item(py, -4).unwrap().extract::<i32>(py).unwrap());
399 assert_eq!(1, seq.get_item(py, -5).unwrap().extract::<i32>(py).unwrap());
400 assert!(seq.get_item(py, 10).is_err());
401 }
402
403 #[test]
408 fn test_seq_del_item() {
409 let gil = Python::acquire_gil();
410 let py = gil.python();
411 let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
412 let seq = v
413 .to_py_object(py)
414 .into_object()
415 .cast_into::<PySequence>(py)
416 .unwrap();
417 assert!(seq.del_item(py, 10).is_err());
418 assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
419 assert!(seq.del_item(py, 0).is_ok());
420 assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
421 assert!(seq.del_item(py, 0).is_ok());
422 assert_eq!(2, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
423 assert!(seq.del_item(py, 0).is_ok());
424 assert_eq!(3, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
425 assert!(seq.del_item(py, 0).is_ok());
426 assert_eq!(5, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
427 assert!(seq.del_item(py, 0).is_ok());
428 assert_eq!(8, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
429 assert!(seq.del_item(py, 0).is_ok());
430 assert_eq!(0, seq.len(py).unwrap());
431 assert!(seq.del_item(py, 0).is_err());
432 }
433
434 #[test]
435 fn test_seq_index() {
436 let gil = Python::acquire_gil();
437 let py = gil.python();
438 let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
439 let seq = v
440 .to_py_object(py)
441 .into_object()
442 .cast_into::<PySequence>(py)
443 .unwrap();
444 assert_eq!(0, seq.index(py, 1i32).unwrap());
445 assert_eq!(2, seq.index(py, 2i32).unwrap());
446 assert_eq!(3, seq.index(py, 3i32).unwrap());
447 assert_eq!(4, seq.index(py, 5i32).unwrap());
448 assert_eq!(5, seq.index(py, 8i32).unwrap());
449 assert!(seq.index(py, 42i32).is_err());
450 }
451
452 #[test]
453 fn test_seq_count() {
454 let gil = Python::acquire_gil();
455 let py = gil.python();
456 let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
457 let seq = v
458 .to_py_object(py)
459 .into_object()
460 .cast_into::<PySequence>(py)
461 .unwrap();
462 assert_eq!(2, seq.count(py, 1i32).unwrap());
463 assert_eq!(1, seq.count(py, 2i32).unwrap());
464 assert_eq!(1, seq.count(py, 3i32).unwrap());
465 assert_eq!(1, seq.count(py, 5i32).unwrap());
466 assert_eq!(1, seq.count(py, 8i32).unwrap());
467 assert_eq!(0, seq.count(py, 42i32).unwrap());
468 }
469
470 #[test]
471 fn test_seq_iter() {
472 let gil = Python::acquire_gil();
473 let py = gil.python();
474 let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];
475 let seq = v
476 .to_py_object(py)
477 .into_object()
478 .cast_into::<PySequence>(py)
479 .unwrap();
480 let mut idx = 0;
481 for el in seq.iter(py).unwrap() {
482 assert_eq!(v[idx], el.unwrap().extract::<i32>(py).unwrap());
483 idx += 1;
484 }
485 assert_eq!(idx, v.len());
486 }
487
488 #[test]
489 fn test_seq_strings() {
490 let gil = Python::acquire_gil();
491 let py = gil.python();
492 let v = vec!["It", "was", "the", "worst", "of", "times"];
493 let seq = v
494 .to_py_object(py)
495 .into_object()
496 .cast_into::<PySequence>(py)
497 .unwrap();
498
499 let bad_needle = "blurst".to_py_object(py);
500 assert_eq!(false, seq.contains(py, bad_needle).unwrap());
501
502 let good_needle = "worst".to_py_object(py);
503 assert_eq!(true, seq.contains(py, good_needle).unwrap());
504 }
505
506 #[test]
507 fn test_seq_concat() {
508 let gil = Python::acquire_gil();
509 let py = gil.python();
510 let v: Vec<i32> = vec![1, 2, 3];
511 let seq = v
512 .to_py_object(py)
513 .into_object()
514 .cast_into::<PySequence>(py)
515 .unwrap();
516 let concat_seq = seq
517 .concat(py, &seq)
518 .unwrap()
519 .cast_into::<PySequence>(py)
520 .unwrap();
521 assert_eq!(6, concat_seq.len(py).unwrap());
522 let concat_v: Vec<i32> = vec![1, 2, 3, 1, 2, 3];
523 for (el, cc) in seq.iter(py).unwrap().zip(concat_v) {
524 assert_eq!(cc, el.unwrap().extract::<i32>(py).unwrap());
525 }
526 }
527
528 #[test]
529 fn test_seq_concat_string() {
530 let gil = Python::acquire_gil();
531 let py = gil.python();
532 let v = "string";
533 let seq = v
534 .to_py_object(py)
535 .into_object()
536 .cast_into::<PySequence>(py)
537 .unwrap();
538 let concat_seq = seq
539 .concat(py, &seq)
540 .unwrap()
541 .cast_into::<PySequence>(py)
542 .unwrap();
543 assert_eq!(12, concat_seq.len(py).unwrap());
544 }
549
550 #[test]
551 fn test_seq_repeat() {
552 let gil = Python::acquire_gil();
553 let py = gil.python();
554 let v = vec!["foo", "bar"];
555 let seq = v
556 .to_py_object(py)
557 .into_object()
558 .cast_into::<PySequence>(py)
559 .unwrap();
560 let repeat_seq = seq
561 .repeat(py, 3)
562 .unwrap()
563 .cast_into::<PySequence>(py)
564 .unwrap();
565 assert_eq!(6, repeat_seq.len(py).unwrap());
566 let repeated = vec!["foo", "bar", "foo", "bar", "foo", "bar"];
567 for (el, rpt) in seq.iter(py).unwrap().zip(repeated.iter()) {
568 assert_eq!(*rpt, el.unwrap().extract::<String>(py).unwrap());
569 }
570 }
571
572 #[test]
573 fn test_list_coercion() {
574 let gil = Python::acquire_gil();
575 let py = gil.python();
576 let v = vec!["foo", "bar"];
577 let seq = v
578 .to_py_object(py)
579 .into_object()
580 .cast_into::<PySequence>(py)
581 .unwrap();
582 assert!(seq.list(py).is_ok());
583 }
584
585 #[test]
586 fn test_strings_coerce_to_lists() {
587 let gil = Python::acquire_gil();
588 let py = gil.python();
589 let v = "foo";
590 let seq = v
591 .to_py_object(py)
592 .into_object()
593 .cast_into::<PySequence>(py)
594 .unwrap();
595 assert!(seq.list(py).is_ok());
596 }
597
598 #[test]
599 fn test_tuple_coercion() {
600 let gil = Python::acquire_gil();
601 let py = gil.python();
602 let v = ("foo", "bar");
603 let seq = v
604 .to_py_object(py)
605 .into_object()
606 .cast_into::<PySequence>(py)
607 .unwrap();
608 assert!(seq.tuple(py).is_ok());
609 }
610
611 #[test]
612 fn test_lists_coerce_to_tuples() {
613 let gil = Python::acquire_gil();
614 let py = gil.python();
615 let v = vec!["foo", "bar"];
616 let seq = v
617 .to_py_object(py)
618 .into_object()
619 .cast_into::<PySequence>(py)
620 .unwrap();
621 assert!(seq.tuple(py).is_ok());
622 }
623
624 #[test]
625 fn test_extract_tuple_to_vec() {
626 let gil = Python::acquire_gil();
627 let py = gil.python();
628 let v: Vec<i32> = py.eval("(1, 2)", None, None).unwrap().extract(py).unwrap();
629 assert!(v == [1, 2]);
630 }
631
632 #[test]
633 fn test_extract_range_to_vec() {
634 let gil = Python::acquire_gil();
635 let py = gil.python();
636 let v: Vec<i32> = py
637 .eval("range(1, 5)", None, None)
638 .unwrap()
639 .extract(py)
640 .unwrap();
641 assert!(v == [1, 2, 3, 4]);
642 }
643
644 #[test]
645 fn test_extract_bytearray_to_vec() {
646 let gil = Python::acquire_gil();
647 let py = gil.python();
648 let v: Vec<u8> = py
649 .eval("bytearray(b'abc')", None, None)
650 .unwrap()
651 .extract(py)
652 .unwrap();
653 assert!(v == b"abc");
654 }
655}