@@ -63,15 +63,38 @@ size_t array_py_index(const WrappedArray& self,
63
63
py::ssize_t stop) {
64
64
array_validate_value (self, value);
65
65
66
- auto end = ArrayIterator{self, convert_py_idx (self, stop)};
66
+ // `list.index` method handles indexes a little differently to most methods. Essentially, any
67
+ // index is allowed, and it's just implicitly clamped to the size of the array. You're allowed
68
+ // to do some stupid things like `["a"].index("a", -100, -200)`, it just gives a not in list
69
+ // error.
70
+
71
+ // Firstly, wrap negative indexes
72
+ auto size = static_cast <py::ssize_t >(self.size ());
73
+ if (start < 0 ) {
74
+ start += size;
75
+ }
76
+ if (stop < 0 ) {
77
+ stop += size;
78
+ }
79
+
80
+ // Clamp to the start of the array
81
+ start = std::max (start, py::ssize_t {0 });
82
+ stop = std::max (stop, py::ssize_t {0 });
67
83
68
- auto location = std::find_if (ArrayIterator{self, convert_py_idx (self, start)}, end,
69
- [&value](const auto & other) { return value.equal (other); });
70
- if (location == end) {
71
- throw py::value_error (
72
- unrealsdk::fmt::format (" {} is not in array" , std::string (py::repr (value))));
84
+ // Make sure the start is actually before the stop
85
+ if (start < stop) {
86
+ // If the stop index is beyond the end, this automatically becomes an end of array iterator
87
+ auto end = ArrayIterator{self, static_cast <size_t >(stop)};
88
+
89
+ auto location = std::find_if (ArrayIterator{self, static_cast <size_t >(start)}, end,
90
+ [&value](const auto & other) { return value.equal (other); });
91
+ if (location != end) {
92
+ return location.idx ;
93
+ }
73
94
}
74
- return location.idx ;
95
+
96
+ throw py::value_error (
97
+ unrealsdk::fmt::format (" {} is not in array" , std::string (py::repr (value))));
75
98
}
76
99
77
100
void array_py_insert (WrappedArray& self, py::ssize_t py_idx, const py::object& value) {
0 commit comments