Skip to main content

rustpython_common/
borrow.rs

1use crate::lock::{
2    MapImmutable, PyImmutableMappedMutexGuard, PyMappedDetachingRwLockReadGuard,
3    PyMappedDetachingRwLockWriteGuard, PyMappedMutexGuard, PyMappedRwLockReadGuard,
4    PyMappedRwLockWriteGuard, PyMutexGuard, PyRwLockReadGuard, PyRwLockWriteGuard,
5};
6use alloc::fmt;
7use core::ops::{Deref, DerefMut};
8
9macro_rules! impl_from {
10    ($lt:lifetime, $gen:ident, $t:ty, $($var:ident($from:ty),)*) => {
11        $(
12            impl<$lt, $gen: ?Sized> From<$from> for $t {
13                fn from(t: $from) -> Self {
14                    Self::$var(t)
15                }
16            }
17        )*
18    };
19}
20
21#[derive(Debug)]
22pub enum BorrowedValue<'a, T: ?Sized> {
23    Ref(&'a T),
24    MuLock(PyMutexGuard<'a, T>),
25    MappedMuLock(PyImmutableMappedMutexGuard<'a, T>),
26    ReadLock(PyRwLockReadGuard<'a, T>),
27    MappedReadLock(PyMappedRwLockReadGuard<'a, T>),
28    MappedDetachingReadLock(PyMappedDetachingRwLockReadGuard<'a, T>),
29}
30impl_from!('a, T, BorrowedValue<'a, T>,
31    Ref(&'a T),
32    MuLock(PyMutexGuard<'a, T>),
33    MappedMuLock(PyImmutableMappedMutexGuard<'a, T>),
34    ReadLock(PyRwLockReadGuard<'a, T>),
35    MappedReadLock(PyMappedRwLockReadGuard<'a, T>),
36    MappedDetachingReadLock(PyMappedDetachingRwLockReadGuard<'a, T>),
37);
38
39impl<'a, T: ?Sized> BorrowedValue<'a, T> {
40    /// Whether reaching the value holds a lock that other threads wait on.
41    ///
42    /// An immutable object hands out a plain reference and answers `false`;
43    /// one whose storage can change hands out a guard. A caller about to wait
44    /// for something unrelated -- a peer, a file, a signal -- can use this to
45    /// decide whether it may keep the borrow for the duration.
46    #[must_use]
47    pub const fn is_locked(&self) -> bool {
48        !matches!(self, Self::Ref(_))
49    }
50
51    pub fn map<U: ?Sized, F>(s: Self, f: F) -> BorrowedValue<'a, U>
52    where
53        F: FnOnce(&T) -> &U,
54    {
55        match s {
56            Self::Ref(r) => BorrowedValue::Ref(f(r)),
57            Self::MuLock(m) => BorrowedValue::MappedMuLock(PyMutexGuard::map_immutable(m, f)),
58            Self::MappedMuLock(m) => {
59                BorrowedValue::MappedMuLock(PyImmutableMappedMutexGuard::map(m, f))
60            }
61            Self::ReadLock(r) => BorrowedValue::MappedReadLock(PyRwLockReadGuard::map(r, f)),
62            Self::MappedReadLock(m) => {
63                BorrowedValue::MappedReadLock(PyMappedRwLockReadGuard::map(m, f))
64            }
65            Self::MappedDetachingReadLock(m) => {
66                BorrowedValue::MappedDetachingReadLock(PyMappedDetachingRwLockReadGuard::map(m, f))
67            }
68        }
69    }
70}
71
72impl<T: ?Sized> Deref for BorrowedValue<'_, T> {
73    type Target = T;
74
75    fn deref(&self) -> &T {
76        match self {
77            Self::Ref(r) => r,
78            Self::MuLock(m) => m,
79            Self::MappedMuLock(m) => m,
80            Self::ReadLock(r) => r,
81            Self::MappedReadLock(m) => m,
82            Self::MappedDetachingReadLock(m) => m,
83        }
84    }
85}
86
87impl fmt::Display for BorrowedValue<'_, str> {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        fmt::Display::fmt(&**self, f)
90    }
91}
92
93#[derive(Debug)]
94pub enum BorrowedValueMut<'a, T: ?Sized> {
95    RefMut(&'a mut T),
96    MuLock(PyMutexGuard<'a, T>),
97    MappedMuLock(PyMappedMutexGuard<'a, T>),
98    WriteLock(PyRwLockWriteGuard<'a, T>),
99    MappedWriteLock(PyMappedRwLockWriteGuard<'a, T>),
100    MappedDetachingWriteLock(PyMappedDetachingRwLockWriteGuard<'a, T>),
101}
102
103impl_from!('a, T, BorrowedValueMut<'a, T>,
104    RefMut(&'a mut T),
105    MuLock(PyMutexGuard<'a, T>),
106    MappedMuLock(PyMappedMutexGuard<'a, T>),
107    WriteLock(PyRwLockWriteGuard<'a, T>),
108    MappedWriteLock(PyMappedRwLockWriteGuard<'a, T>),
109    MappedDetachingWriteLock(PyMappedDetachingRwLockWriteGuard<'a, T>),
110);
111
112impl<'a, T: ?Sized> BorrowedValueMut<'a, T> {
113    pub fn map<U: ?Sized, F>(s: Self, f: F) -> BorrowedValueMut<'a, U>
114    where
115        F: FnOnce(&mut T) -> &mut U,
116    {
117        match s {
118            Self::RefMut(r) => BorrowedValueMut::RefMut(f(r)),
119            Self::MuLock(m) => BorrowedValueMut::MappedMuLock(PyMutexGuard::map(m, f)),
120            Self::MappedMuLock(m) => BorrowedValueMut::MappedMuLock(PyMappedMutexGuard::map(m, f)),
121            Self::WriteLock(r) => BorrowedValueMut::MappedWriteLock(PyRwLockWriteGuard::map(r, f)),
122            Self::MappedWriteLock(m) => {
123                BorrowedValueMut::MappedWriteLock(PyMappedRwLockWriteGuard::map(m, f))
124            }
125            Self::MappedDetachingWriteLock(m) => BorrowedValueMut::MappedDetachingWriteLock(
126                PyMappedDetachingRwLockWriteGuard::map(m, f),
127            ),
128        }
129    }
130}
131
132impl<T: ?Sized> Deref for BorrowedValueMut<'_, T> {
133    type Target = T;
134
135    fn deref(&self) -> &T {
136        match self {
137            Self::RefMut(r) => r,
138            Self::MuLock(m) => m,
139            Self::MappedMuLock(m) => m,
140            Self::WriteLock(w) => w,
141            Self::MappedWriteLock(w) => w,
142            Self::MappedDetachingWriteLock(w) => w,
143        }
144    }
145}
146
147impl<T: ?Sized> DerefMut for BorrowedValueMut<'_, T> {
148    fn deref_mut(&mut self) -> &mut T {
149        match self {
150            Self::RefMut(r) => r,
151            Self::MuLock(m) => &mut *m,
152            Self::MappedMuLock(m) => &mut *m,
153            Self::WriteLock(w) => &mut *w,
154            Self::MappedWriteLock(w) => &mut *w,
155            Self::MappedDetachingWriteLock(w) => &mut *w,
156        }
157    }
158}