Show More
@@ -25,6 +25,7 b'' | |||||
25 | use crate::exceptions::AlreadyBorrowed; |
|
25 | use crate::exceptions::AlreadyBorrowed; | |
26 | use cpython::{PyClone, PyObject, PyResult, Python}; |
|
26 | use cpython::{PyClone, PyObject, PyResult, Python}; | |
27 | use std::cell::{Cell, Ref, RefCell, RefMut}; |
|
27 | use std::cell::{Cell, Ref, RefCell, RefMut}; | |
|
28 | use std::ops::{Deref, DerefMut}; | |||
28 |
|
29 | |||
29 | /// Manages the shared state between Python and Rust |
|
30 | /// Manages the shared state between Python and Rust | |
30 | #[derive(Debug, Default)] |
|
31 | #[derive(Debug, Default)] | |
@@ -333,17 +334,29 b' impl<T> PyLeaked<T> {' | |||||
333 | } |
|
334 | } | |
334 | } |
|
335 | } | |
335 |
|
336 | |||
336 |
/// |
|
337 | /// Immutably borrows the wrapped value. | |
337 | pub fn get_ref<'a>(&'a self, _py: Python<'a>) -> &'a T { |
|
338 | pub fn try_borrow<'a>( | |
338 | self.data.as_ref().unwrap() |
|
339 | &'a self, | |
|
340 | py: Python<'a>, | |||
|
341 | ) -> PyResult<PyLeakedRef<'a, T>> { | |||
|
342 | Ok(PyLeakedRef { | |||
|
343 | _py: py, | |||
|
344 | data: self.data.as_ref().unwrap(), | |||
|
345 | }) | |||
339 | } |
|
346 | } | |
340 |
|
347 | |||
341 |
/// |
|
348 | /// Mutably borrows the wrapped value. | |
342 | /// |
|
349 | /// | |
343 | /// Typically `T` is an iterator. If `T` is an immutable reference, |
|
350 | /// Typically `T` is an iterator. If `T` is an immutable reference, | |
344 | /// `get_mut()` is useless since the inner value can't be mutated. |
|
351 | /// `get_mut()` is useless since the inner value can't be mutated. | |
345 | pub fn get_mut<'a>(&'a mut self, _py: Python<'a>) -> &'a mut T { |
|
352 | pub fn try_borrow_mut<'a>( | |
346 | self.data.as_mut().unwrap() |
|
353 | &'a mut self, | |
|
354 | py: Python<'a>, | |||
|
355 | ) -> PyResult<PyLeakedRefMut<'a, T>> { | |||
|
356 | Ok(PyLeakedRefMut { | |||
|
357 | _py: py, | |||
|
358 | data: self.data.as_mut().unwrap(), | |||
|
359 | }) | |||
347 | } |
|
360 | } | |
348 |
|
361 | |||
349 | /// Converts the inner value by the given function. |
|
362 | /// Converts the inner value by the given function. | |
@@ -389,6 +402,40 b' impl<T> Drop for PyLeaked<T> {' | |||||
389 | } |
|
402 | } | |
390 | } |
|
403 | } | |
391 |
|
404 | |||
|
405 | /// Immutably borrowed reference to a leaked value. | |||
|
406 | pub struct PyLeakedRef<'a, T> { | |||
|
407 | _py: Python<'a>, | |||
|
408 | data: &'a T, | |||
|
409 | } | |||
|
410 | ||||
|
411 | impl<T> Deref for PyLeakedRef<'_, T> { | |||
|
412 | type Target = T; | |||
|
413 | ||||
|
414 | fn deref(&self) -> &T { | |||
|
415 | self.data | |||
|
416 | } | |||
|
417 | } | |||
|
418 | ||||
|
419 | /// Mutably borrowed reference to a leaked value. | |||
|
420 | pub struct PyLeakedRefMut<'a, T> { | |||
|
421 | _py: Python<'a>, | |||
|
422 | data: &'a mut T, | |||
|
423 | } | |||
|
424 | ||||
|
425 | impl<T> Deref for PyLeakedRefMut<'_, T> { | |||
|
426 | type Target = T; | |||
|
427 | ||||
|
428 | fn deref(&self) -> &T { | |||
|
429 | self.data | |||
|
430 | } | |||
|
431 | } | |||
|
432 | ||||
|
433 | impl<T> DerefMut for PyLeakedRefMut<'_, T> { | |||
|
434 | fn deref_mut(&mut self) -> &mut T { | |||
|
435 | self.data | |||
|
436 | } | |||
|
437 | } | |||
|
438 | ||||
392 | /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator. |
|
439 | /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator. | |
393 | /// |
|
440 | /// | |
394 | /// TODO: this is a bit awkward to use, and a better (more complicated) |
|
441 | /// TODO: this is a bit awkward to use, and a better (more complicated) | |
@@ -457,7 +504,8 b' macro_rules! py_shared_iterator {' | |||||
457 | def __next__(&self) -> PyResult<$success_type> { |
|
504 | def __next__(&self) -> PyResult<$success_type> { | |
458 | let mut inner_opt = self.inner(py).borrow_mut(); |
|
505 | let mut inner_opt = self.inner(py).borrow_mut(); | |
459 | if let Some(leaked) = inner_opt.as_mut() { |
|
506 | if let Some(leaked) = inner_opt.as_mut() { | |
460 |
|
|
507 | let mut iter = leaked.try_borrow_mut(py)?; | |
|
508 | match iter.next() { | |||
461 | None => { |
|
509 | None => { | |
462 | // replace Some(inner) by None, drop $leaked |
|
510 | // replace Some(inner) by None, drop $leaked | |
463 | inner_opt.take(); |
|
511 | inner_opt.take(); | |
@@ -512,6 +560,28 b' mod test {' | |||||
512 | } |
|
560 | } | |
513 |
|
561 | |||
514 | #[test] |
|
562 | #[test] | |
|
563 | fn test_leaked_borrow() { | |||
|
564 | let (gil, owner) = prepare_env(); | |||
|
565 | let py = gil.python(); | |||
|
566 | let leaked = owner.string_shared(py).leak_immutable().unwrap(); | |||
|
567 | let leaked_ref = leaked.try_borrow(py).unwrap(); | |||
|
568 | assert_eq!(*leaked_ref, "new"); | |||
|
569 | } | |||
|
570 | ||||
|
571 | #[test] | |||
|
572 | fn test_leaked_borrow_mut() { | |||
|
573 | let (gil, owner) = prepare_env(); | |||
|
574 | let py = gil.python(); | |||
|
575 | let leaked = owner.string_shared(py).leak_immutable().unwrap(); | |||
|
576 | let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) }; | |||
|
577 | let mut leaked_ref = leaked_iter.try_borrow_mut(py).unwrap(); | |||
|
578 | assert_eq!(leaked_ref.next(), Some('n')); | |||
|
579 | assert_eq!(leaked_ref.next(), Some('e')); | |||
|
580 | assert_eq!(leaked_ref.next(), Some('w')); | |||
|
581 | assert_eq!(leaked_ref.next(), None); | |||
|
582 | } | |||
|
583 | ||||
|
584 | #[test] | |||
515 | fn test_borrow_mut_while_leaked() { |
|
585 | fn test_borrow_mut_while_leaked() { | |
516 | let (gil, owner) = prepare_env(); |
|
586 | let (gil, owner) = prepare_env(); | |
517 | let py = gil.python(); |
|
587 | let py = gil.python(); |
General Comments 0
You need to be logged in to leave comments.
Login now