Show More
@@ -25,6 +25,7 b'' | |||
|
25 | 25 | use crate::exceptions::AlreadyBorrowed; |
|
26 | 26 | use cpython::{PyClone, PyObject, PyResult, Python}; |
|
27 | 27 | use std::cell::{Cell, Ref, RefCell, RefMut}; |
|
28 | use std::ops::{Deref, DerefMut}; | |
|
28 | 29 | |
|
29 | 30 | /// Manages the shared state between Python and Rust |
|
30 | 31 | #[derive(Debug, Default)] |
@@ -333,17 +334,29 b' impl<T> PyLeaked<T> {' | |||
|
333 | 334 | } |
|
334 | 335 | } |
|
335 | 336 | |
|
336 |
/// |
|
|
337 | pub fn get_ref<'a>(&'a self, _py: Python<'a>) -> &'a T { | |
|
338 | self.data.as_ref().unwrap() | |
|
337 | /// Immutably borrows the wrapped value. | |
|
338 | pub fn try_borrow<'a>( | |
|
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 | 350 | /// Typically `T` is an iterator. If `T` is an immutable reference, |
|
344 | 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 { | |
|
346 | self.data.as_mut().unwrap() | |
|
352 | pub fn try_borrow_mut<'a>( | |
|
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 | 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 | 439 | /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator. |
|
393 | 440 | /// |
|
394 | 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 | 504 | def __next__(&self) -> PyResult<$success_type> { |
|
458 | 505 | let mut inner_opt = self.inner(py).borrow_mut(); |
|
459 | 506 | if let Some(leaked) = inner_opt.as_mut() { |
|
460 |
|
|
|
507 | let mut iter = leaked.try_borrow_mut(py)?; | |
|
508 | match iter.next() { | |
|
461 | 509 | None => { |
|
462 | 510 | // replace Some(inner) by None, drop $leaked |
|
463 | 511 | inner_opt.take(); |
@@ -512,6 +560,28 b' mod test {' | |||
|
512 | 560 | } |
|
513 | 561 | |
|
514 | 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 | 585 | fn test_borrow_mut_while_leaked() { |
|
516 | 586 | let (gil, owner) = prepare_env(); |
|
517 | 587 | let py = gil.python(); |
General Comments 0
You need to be logged in to leave comments.
Login now