Skip to content

Commit 16bed5b

Browse files
committed
put wrap_index to SequenceIndexOp
1 parent 38b1f59 commit 16bed5b

File tree

5 files changed

+39
-27
lines changed

5 files changed

+39
-27
lines changed

stdlib/src/mmap.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod mmap {
1414
protocol::{
1515
BufferDescriptor, BufferMethods, PyBuffer, PyMappingMethods, PySequenceMethods,
1616
},
17-
sliceable::{wrap_index, SaturatedSlice, SequenceIndex, SequenceIndexOp},
17+
sliceable::{SaturatedSlice, SequenceIndex, SequenceIndexOp},
1818
types::{AsBuffer, AsMapping, AsSequence, Constructor},
1919
AsObject, FromArgs, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
2020
TryFromBorrowedObject, VirtualMachine,
@@ -918,7 +918,8 @@ mod mmap {
918918
}
919919

920920
fn getitem_by_index(&self, i: isize, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
921-
let i = wrap_index(i, self.len())
921+
let i = i
922+
.wrapped_at(self.len())
922923
.ok_or_else(|| vm.new_index_error("mmap index out of range".to_owned()))?;
923924

924925
let b = match self.check_valid(vm)?.deref().as_ref().unwrap() {
@@ -999,7 +1000,8 @@ mod mmap {
9991000
value: PyObjectRef,
10001001
vm: &VirtualMachine,
10011002
) -> PyResult<()> {
1002-
let i = wrap_index(i, zelf.len())
1003+
let i = i
1004+
.wrapped_at(zelf.len())
10031005
.ok_or_else(|| vm.new_index_error("mmap index out of range".to_owned()))?;
10041006

10051007
let b = value_from_object(vm, &value)?;

vm/src/builtins/memory.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
protocol::{
1818
BufferDescriptor, BufferMethods, PyBuffer, PyMappingMethods, PySequenceMethods, VecBuffer,
1919
},
20-
sliceable::wrap_index,
20+
sliceable::SequenceIndexOp,
2121
types::{AsBuffer, AsMapping, AsSequence, Comparable, Constructor, Hashable, PyComparisonOp},
2222
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
2323
TryFromBorrowedObject, TryFromObject, VirtualMachine,
@@ -243,7 +243,8 @@ impl PyMemoryView {
243243
));
244244
}
245245
let (shape, stride, suboffset) = self.desc.dim_desc[0];
246-
let index = wrap_index(i, shape)
246+
let index = i
247+
.wrapped_at(shape)
247248
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))?;
248249
let index = index as isize * stride + suboffset;
249250
let pos = (index + self.start as isize) as usize;
@@ -292,7 +293,8 @@ impl PyMemoryView {
292293
return Err(vm.new_not_implemented_error("sub-views are not implemented".to_owned()));
293294
}
294295
let (shape, stride, suboffset) = self.desc.dim_desc[0];
295-
let index = wrap_index(i, shape)
296+
let index = i
297+
.wrapped_at(shape)
296298
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))?;
297299
let index = index as isize * stride + suboffset;
298300
let pos = (index + self.start as isize) as usize;

vm/src/protocol/buffer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
lock::{MapImmutable, PyMutex, PyMutexGuard},
88
},
99
object::PyObjectPayload,
10-
sliceable::wrap_index,
10+
sliceable::SequenceIndexOp,
1111
types::{Constructor, Unconstructible},
1212
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject,
1313
VirtualMachine,
@@ -255,7 +255,7 @@ impl BufferDescriptor {
255255
.cloned()
256256
.zip_eq(self.dim_desc.iter().cloned())
257257
{
258-
let i = wrap_index(i, shape).ok_or_else(|| {
258+
let i = i.wrapped_at(shape).ok_or_else(|| {
259259
vm.new_index_error(format!("index out of bounds on dimension {}", i))
260260
})?;
261261
pos += i as isize * stride + suboffset;

vm/src/sliceable.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ pub trait SliceableSequenceOp {
176176
fn len(&self) -> usize;
177177

178178
fn wrap_index(&self, p: isize) -> Option<usize> {
179-
wrap_index(p, self.len())
179+
p.wrapped_at(self.len())
180180
}
181181

182182
fn saturate_index(&self, p: isize) -> usize {
@@ -292,28 +292,33 @@ impl SequenceIndex {
292292
}
293293
}
294294

295-
// Use PySliceableSequence::wrap_index for implementors
296-
pub fn wrap_index(p: isize, len: usize) -> Option<usize> {
297-
let neg = p.is_negative();
298-
let p = p.wrapping_abs() as usize;
299-
if neg {
300-
len.checked_sub(p)
301-
} else if p >= len {
302-
None
303-
} else {
304-
Some(p)
305-
}
306-
}
307-
308295
pub trait SequenceIndexOp {
309296
// Saturate p in range [0, len] inclusive
310297
fn saturated_at(&self, len: usize) -> usize;
298+
// Use PySliceableSequence::wrap_index for implementors
299+
fn wrapped_at(&self, len: usize) -> Option<usize>;
311300
}
312301

313302
impl SequenceIndexOp for isize {
314303
fn saturated_at(&self, len: usize) -> usize {
315304
let len = len.to_isize().unwrap_or(Self::MAX);
316-
*self.clamp(&0, &len) as usize
305+
let mut p = *self;
306+
if p < 0 {
307+
p += len;
308+
}
309+
p.clamp(0, len) as usize
310+
}
311+
312+
fn wrapped_at(&self, len: usize) -> Option<usize> {
313+
let neg = self.is_negative();
314+
let p = self.unsigned_abs();
315+
if neg {
316+
len.checked_sub(p)
317+
} else if p >= len {
318+
None
319+
} else {
320+
Some(p)
321+
}
317322
}
318323
}
319324

@@ -327,6 +332,9 @@ impl SequenceIndexOp for BigInt {
327332
self.try_into().unwrap_or(len)
328333
}
329334
}
335+
fn wrapped_at(&self, _len: usize) -> Option<usize> {
336+
unimplemented!("please add one once we need it")
337+
}
330338
}
331339

332340
/// A saturated slice with values ranging in [isize::MIN, isize::MAX]. Used for

vm/src/stdlib/collections.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod _collections {
1313
protocol::{PyIterReturn, PySequenceMethods},
1414
recursion::ReprGuard,
1515
sequence::MutObjectSequenceOp,
16-
sliceable::{self, SequenceIndexOp},
16+
sliceable::SequenceIndexOp,
1717
types::{
1818
AsSequence, Comparable, Constructor, Hashable, Initializer, IterNext, IterNextIterable,
1919
Iterable, PyComparisonOp, Unhashable,
@@ -279,15 +279,15 @@ mod _collections {
279279
#[pymethod(magic)]
280280
fn getitem(&self, idx: isize, vm: &VirtualMachine) -> PyResult {
281281
let deque = self.borrow_deque();
282-
sliceable::wrap_index(idx, deque.len())
282+
idx.wrapped_at(deque.len())
283283
.and_then(|i| deque.get(i).cloned())
284284
.ok_or_else(|| vm.new_index_error("deque index out of range".to_owned()))
285285
}
286286

287287
#[pymethod(magic)]
288288
fn setitem(&self, idx: isize, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
289289
let mut deque = self.borrow_deque_mut();
290-
sliceable::wrap_index(idx, deque.len())
290+
idx.wrapped_at(deque.len())
291291
.and_then(|i| deque.get_mut(i))
292292
.map(|x| *x = value)
293293
.ok_or_else(|| vm.new_index_error("deque index out of range".to_owned()))
@@ -296,7 +296,7 @@ mod _collections {
296296
#[pymethod(magic)]
297297
fn delitem(&self, idx: isize, vm: &VirtualMachine) -> PyResult<()> {
298298
let mut deque = self.borrow_deque_mut();
299-
sliceable::wrap_index(idx, deque.len())
299+
idx.wrapped_at(deque.len())
300300
.and_then(|i| deque.remove(i).map(drop))
301301
.ok_or_else(|| vm.new_index_error("deque index out of range".to_owned()))
302302
}

0 commit comments

Comments
 (0)