Show More
@@ -314,6 +314,44 b' py_class!(pub class MixedIndex |py| {' | |||||
314 |
|
314 | |||
315 | }); |
|
315 | }); | |
316 |
|
316 | |||
|
317 | /// Take a (potentially) mmap'ed buffer, and return the underlying Python | |||
|
318 | /// buffer along with the Rust slice into said buffer. We need to keep the | |||
|
319 | /// Python buffer around, otherwise we'd get a dangling pointer once the buffer | |||
|
320 | /// is freed from Python's side. | |||
|
321 | /// | |||
|
322 | /// # Safety | |||
|
323 | /// | |||
|
324 | /// The caller must make sure that the buffer is kept around for at least as | |||
|
325 | /// long as the slice. | |||
|
326 | #[deny(unsafe_op_in_unsafe_fn)] | |||
|
327 | unsafe fn mmap_keeparound( | |||
|
328 | py: Python, | |||
|
329 | data: PyObject, | |||
|
330 | ) -> PyResult<( | |||
|
331 | PyBuffer, | |||
|
332 | Box<dyn std::ops::Deref<Target = [u8]> + Send + 'static>, | |||
|
333 | )> { | |||
|
334 | let buf = PyBuffer::get(py, &data)?; | |||
|
335 | let len = buf.item_count(); | |||
|
336 | ||||
|
337 | // Build a slice from the mmap'ed buffer data | |||
|
338 | let cbuf = buf.buf_ptr(); | |||
|
339 | let bytes = if std::mem::size_of::<u8>() == buf.item_size() | |||
|
340 | && buf.is_c_contiguous() | |||
|
341 | && u8::is_compatible_format(buf.format()) | |||
|
342 | { | |||
|
343 | unsafe { std::slice::from_raw_parts(cbuf as *const u8, len) } | |||
|
344 | } else { | |||
|
345 | return Err(PyErr::new::<ValueError, _>( | |||
|
346 | py, | |||
|
347 | "Nodemap data buffer has an invalid memory representation" | |||
|
348 | .to_string(), | |||
|
349 | )); | |||
|
350 | }; | |||
|
351 | ||||
|
352 | Ok((buf, Box::new(bytes))) | |||
|
353 | } | |||
|
354 | ||||
317 | impl MixedIndex { |
|
355 | impl MixedIndex { | |
318 | fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> { |
|
356 | fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> { | |
319 | Self::create_instance( |
|
357 | Self::create_instance( | |
@@ -427,29 +465,12 b' impl MixedIndex {' | |||||
427 | docket: PyObject, |
|
465 | docket: PyObject, | |
428 | nm_data: PyObject, |
|
466 | nm_data: PyObject, | |
429 | ) -> PyResult<PyObject> { |
|
467 | ) -> PyResult<PyObject> { | |
430 | let buf = PyBuffer::get(py, &nm_data)?; |
|
468 | // Safety: we keep the buffer around inside the class as `nodemap_mmap` | |
|
469 | let (buf, bytes) = unsafe { mmap_keeparound(py, nm_data)? }; | |||
431 | let len = buf.item_count(); |
|
470 | let len = buf.item_count(); | |
432 |
|
||||
433 | // Build a slice from the mmap'ed buffer data |
|
|||
434 | let cbuf = buf.buf_ptr(); |
|
|||
435 | let bytes = if std::mem::size_of::<u8>() == buf.item_size() |
|
|||
436 | && buf.is_c_contiguous() |
|
|||
437 | && u8::is_compatible_format(buf.format()) |
|
|||
438 | { |
|
|||
439 | unsafe { std::slice::from_raw_parts(cbuf as *const u8, len) } |
|
|||
440 | } else { |
|
|||
441 | return Err(PyErr::new::<ValueError, _>( |
|
|||
442 | py, |
|
|||
443 | "Nodemap data buffer has an invalid memory representation" |
|
|||
444 | .to_string(), |
|
|||
445 | )); |
|
|||
446 | }; |
|
|||
447 |
|
||||
448 | // Keep a reference to the mmap'ed buffer, otherwise we get a dangling |
|
|||
449 | // pointer. |
|
|||
450 | self.nodemap_mmap(py).borrow_mut().replace(buf); |
|
471 | self.nodemap_mmap(py).borrow_mut().replace(buf); | |
451 |
|
472 | |||
452 |
let mut nt = NodeTree::load_bytes( |
|
473 | let mut nt = NodeTree::load_bytes(bytes, len); | |
453 |
|
474 | |||
454 | let data_tip = docket |
|
475 | let data_tip = docket | |
455 | .getattr(py, "tip_rev")? |
|
476 | .getattr(py, "tip_rev")? |
General Comments 0
You need to be logged in to leave comments.
Login now