Skip to content

Commit eed1537

Browse files
committed
fix: address CR problems and fixed size method
1 parent e785f99 commit eed1537

File tree

3 files changed

+30
-48
lines changed

3 files changed

+30
-48
lines changed

Lib/test/test_mmap.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,9 @@ def test_flush_return_value(self):
736736
mm.write(b'python')
737737
result = mm.flush()
738738
self.assertIsNone(result)
739-
# TODO: flush doesn't support range righ
740-
#if sys.platform.startswith('linux'):
739+
# TODO: RUSTPYTHON
740+
# Right now memmap2 doesn't throw OSError when offet is not a multiple of mmap.PAGESIZE on Linux
741+
# if sys.platform.startswith('linux'):
741742
# 'offset' must be a multiple of mmap.PAGESIZE on Linux.
742743
# See bpo-34754 for details.
743744
# self.assertRaises(OSError, mm.flush, 1, len(b'python'))

stdlib/src/mmap.rs

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ mod mmap {
1515
protocol::{
1616
BufferDescriptor, BufferMethods, PyBuffer, PyMappingMethods, PySequenceMethods,
1717
},
18-
sliceable::{SaturatedSlice, SequenceIndex},
18+
sliceable::{saturate_index, wrap_index, SaturatedSlice, SequenceIndex},
1919
types::{AsBuffer, AsMapping, AsSequence, Constructor},
2020
AsObject, FromArgs, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
2121
TryFromBorrowedObject, VirtualMachine,
2222
};
2323
use crossbeam_utils::atomic::AtomicCell;
2424
use memmap2::{Advice, Mmap, MmapMut, MmapOptions};
25+
use nix::unistd;
2526
use std::fs::File;
2627
use std::io::Write;
2728
use std::ops::{Deref, DerefMut};
@@ -143,7 +144,7 @@ mod mmap {
143144
struct PyMmap {
144145
closed: AtomicCell<bool>,
145146
mmap: PyMutex<Option<MmapObj>>,
146-
_fd: RawFd,
147+
fd: RawFd,
147148
offset: isize,
148149
size: AtomicCell<isize>,
149150
pos: AtomicCell<isize>, // relative to offset
@@ -297,7 +298,7 @@ mod mmap {
297298
),
298299
)
299300
} else {
300-
let new_fd = nix::unistd::dup(fd).map_err(|e| vm.new_os_error(e.to_string()))?;
301+
let new_fd = unistd::dup(fd).map_err(|e| vm.new_os_error(e.to_string()))?;
301302
let mmap = match access {
302303
AccessMode::Default | AccessMode::Write => MmapObj::Write(
303304
unsafe { mmap_opt.map_mut(fd) }
@@ -317,7 +318,7 @@ mod mmap {
317318
let m_obj = Self {
318319
closed: AtomicCell::new(false),
319320
mmap: PyMutex::new(Some(mmap)),
320-
_fd: fd,
321+
fd,
321322
offset,
322323
size: AtomicCell::new(map_size),
323324
pos: AtomicCell::new(0),
@@ -518,28 +519,13 @@ mod mmap {
518519
fn get_find_range(&self, options: FindOptions) -> (usize, usize) {
519520
let pos = self.inner_pos();
520521
let size = self.inner_size();
521-
let mut start = options.start.unwrap_or(pos);
522-
let mut end = options.end.unwrap_or(size);
522+
let start = options.start.unwrap_or(pos);
523+
let end = options.end.unwrap_or(size);
523524

524-
if start < 0 {
525-
start += size;
526-
}
527-
if start < 0 {
528-
start = 0;
529-
} else if start > size {
530-
start = size;
531-
}
532-
533-
if end < 0 {
534-
end += size;
535-
}
536-
if end < 0 {
537-
end = 0;
538-
} else if end > size {
539-
end = size;
540-
}
541-
542-
(start as usize, end as usize)
525+
(
526+
saturate_index(start, size.try_into().unwrap()),
527+
saturate_index(end, size.try_into().unwrap()),
528+
)
543529
}
544530

545531
#[pymethod]
@@ -827,8 +813,15 @@ mod mmap {
827813
}
828814

829815
#[pymethod]
830-
fn size(&self) -> isize {
831-
self.inner_size()
816+
fn size(&self, vm: &VirtualMachine) -> PyResult<PyIntRef> {
817+
let new_fd = unistd::dup(self.fd).map_err(|e| vm.new_os_error(e.to_string()))?;
818+
let file = unsafe { File::from_raw_fd(new_fd) };
819+
let file_len = match file.metadata() {
820+
Ok(m) => m.len(),
821+
Err(e) => return Err(vm.new_os_error(e.to_string())),
822+
};
823+
824+
Ok(PyInt::from(file_len).into_ref(vm))
832825
}
833826

834827
#[pymethod]
@@ -889,15 +882,9 @@ mod mmap {
889882
Ok(())
890883
}
891884

892-
fn get_item_by_index(&self, mut i: isize, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
893-
let size = self.inner_size();
894-
895-
if i < 0 {
896-
i += size;
897-
}
898-
if i < 0 || i >= size {
899-
return Err(vm.new_index_error("mmap index out of range".to_owned()));
900-
}
885+
fn get_item_by_index(&self, i: isize, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
886+
let i = wrap_index(i, self.len())
887+
.ok_or_else(|| vm.new_index_error("mmap index out of range".to_owned()))?;
901888

902889
let b = match self.check_valid(vm)?.deref().as_ref().unwrap() {
903890
MmapObj::Read(mmap) => mmap[i as usize],
@@ -973,18 +960,12 @@ mod mmap {
973960

974961
fn setitem_by_index(
975962
zelf: PyRef<Self>,
976-
mut i: isize,
963+
i: isize,
977964
value: PyObjectRef,
978965
vm: &VirtualMachine,
979966
) -> PyResult<()> {
980-
let size = zelf.inner_size();
981-
982-
if i < 0 {
983-
i += size;
984-
}
985-
if i < 0 || i >= size {
986-
return Err(vm.new_index_error("mmap index out of range".to_owned()));
987-
}
967+
let i = wrap_index(i, zelf.len())
968+
.ok_or_else(|| vm.new_index_error("mmap index out of range".to_owned()))?;
988969

989970
zelf.check_writable(vm)?;
990971
let b = value_from_object(vm, &value)?;

vm/src/sliceable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl TryFromBorrowedObject for SequenceIndex {
287287
}
288288

289289
// Use PySliceableSequence::wrap_index for implementors
290-
pub(crate) fn wrap_index(p: isize, len: usize) -> Option<usize> {
290+
pub fn wrap_index(p: isize, len: usize) -> Option<usize> {
291291
let neg = p.is_negative();
292292
let p = p.wrapping_abs() as usize;
293293
if neg {

0 commit comments

Comments
 (0)