rust/hg-cpython/src/revlog.rs
changeset 51184 8c4e8d06432e
parent 51183 8ade5e6cdb61
child 51187 6ec8387eb0be
equal deleted inserted replaced
51183:8ade5e6cdb61 51184:8c4e8d06432e
   312         self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py)
   312         self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py)
   313     }
   313     }
   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(
   320             py,
   358             py,
   321             RefCell::new(cindex::Index::new(py, cindex)?),
   359             RefCell::new(cindex::Index::new(py, cindex)?),
   425         &self,
   463         &self,
   426         py: Python,
   464         py: Python,
   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(Box::new(bytes), len);
   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")?
   456             .extract::<BaseRevision>(py)?
   477             .extract::<BaseRevision>(py)?
   457             .into();
   478             .into();