| 636 | } |
| 637 | |
| 638 | fn do_sort( |
| 639 | vm: &VirtualMachine, |
| 640 | values: &mut Vec<PyObjectRef>, |
| 641 | key_func: Option<PyObjectRef>, |
| 642 | reverse: bool, |
| 643 | ) -> PyResult<()> { |
| 644 | // CPython uses __lt__ for all comparisons in sort. |
| 645 | // try_sort_by_gt expects is_gt(a, b) = true when a should come AFTER b. |
| 646 | let cmp = |a: &PyObjectRef, b: &PyObjectRef| { |
| 647 | if reverse { |
| 648 | // Descending: a comes after b when a < b |
| 649 | a.rich_compare_bool(b, PyComparisonOp::Lt, vm) |
| 650 | } else { |
| 651 | // Ascending: a comes after b when b < a |
| 652 | b.rich_compare_bool(a, PyComparisonOp::Lt, vm) |
| 653 | } |
| 654 | }; |
| 655 | |
| 656 | if let Some(ref key_func) = key_func { |
| 657 | let mut items = values |
| 658 | .iter() |
| 659 | .map(|x| Ok((x.clone(), key_func.call((x.clone(),), vm)?))) |
| 660 | .collect::<Result<Vec<_>, _>>()?; |
| 661 | timsort::try_sort_by_gt(&mut items, |a, b| cmp(&a.1, &b.1))?; |
| 662 | *values = items.into_iter().map(|(val, _)| val).collect(); |
| 663 | } else { |
| 664 | timsort::try_sort_by_gt(values, cmp)?; |
| 665 | } |
| 666 | |
| 667 | Ok(()) |
| 668 | } |
| 669 | |
| 670 | #[pyclass(module = false, name = "list_iterator", traverse)] |
| 671 | #[derive(Debug)] |