@@ -63,15 +63,38 @@ size_t array_py_index(const WrappedArray& self,
6363 py::ssize_t stop) {
6464 array_validate_value (self, value);
6565
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 });
6783
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+ }
7394 }
74- return location.idx ;
95+
96+ throw py::value_error (
97+ unrealsdk::fmt::format (" {} is not in array" , std::string (py::repr (value))));
7598}
7699
77100void array_py_insert (WrappedArray& self, py::ssize_t py_idx, const py::object& value) {
0 commit comments