Skip to main content

hexga_core/
guard.rs

1use super::*;
2use core::ops::{Deref, DerefMut};
3
4pub trait Guarded<T: ?Sized>
5{
6    type Guard<'a>: Deref<Target = T>
7    where
8        Self: 'a;
9    /// Can panic on exceptional behavior (ex poisoned mutex)
10    fn get<'a>(&'a self) -> Self::Guard<'a>;
11}
12pub trait TryGuarded<T: ?Sized>: Guarded<T>
13{
14    type Error<'a>: Debug
15    where
16        Self: 'a;
17    fn try_get<'a>(&'a self) -> Result<Self::Guard<'a>, Self::Error<'a>>;
18}
19
20pub trait GuardedMut<T: ?Sized>
21{
22    type GuardMut<'a>: DerefMut<Target = T>
23    where
24        Self: 'a;
25    /// Can panic on exceptional behavior (ex poisoned mutex)
26    fn get_mut<'a>(&'a self) -> Self::GuardMut<'a>;
27}
28pub trait TryGuardedMut<T: ?Sized>: GuardedMut<T>
29{
30    type Error<'a>: Debug
31    where
32        Self: 'a;
33    fn try_get_mut<'a>(&'a self) -> Result<Self::GuardMut<'a>, Self::Error<'a>>;
34}
35
36pub trait Guard<'a, T>: Deref<Target = T>
37where
38    T: ?Sized,
39{
40    type Mapped<U>
41    where
42        U: 'a + ?Sized;
43    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
44    where
45        F: FnOnce(&T) -> &U,
46        U: 'a + ?Sized;
47}
48pub trait GuardMut<'a, T>: DerefMut<Target = T>
49where
50    T: ?Sized,
51{
52    type MappedMut<U>
53    where
54        U: 'a + ?Sized;
55    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
56    where
57        F: FnOnce(&mut T) -> &mut U,
58        U: 'a + ?Sized;
59}
60
61pub fn map<'a, G, T, U, F>(guard: G, f: F) -> G::Mapped<U>
62where
63    F: FnOnce(&T) -> &U,
64    T: ?Sized,
65    G: Guard<'a, T>,
66{
67    G::guard_map(guard, f)
68}
69
70pub fn map_mut<'a, G, T, U, F>(guard: G, f: F) -> G::MappedMut<U>
71where
72    F: FnOnce(&mut T) -> &mut U,
73    T: ?Sized,
74    G: GuardMut<'a, T>,
75{
76    G::guard_map_mut(guard, f)
77}
78
79// implementations:
80
81impl<'a, T> Guard<'a, T> for &'a T
82{
83    type Mapped<U>
84        = &'a U
85    where
86        U: 'a + ?Sized;
87    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
88    where
89        F: FnOnce(&'a T) -> &'a U,
90        U: 'a + ?Sized,
91    {
92        f(self)
93    }
94}
95impl<'a, T> Guard<'a, T> for &'a mut T
96{
97    type Mapped<U>
98        = &'a U
99    where
100        U: 'a + ?Sized;
101    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
102    where
103        F: FnOnce(&'a T) -> &'a U,
104        U: 'a + ?Sized,
105    {
106        f(self)
107    }
108}
109impl<'a, T> GuardMut<'a, T> for &'a mut T
110{
111    type MappedMut<U>
112        = &'a mut U
113    where
114        U: 'a + ?Sized;
115    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
116    where
117        F: FnOnce(&'a mut T) -> &'a mut U,
118        U: 'a + ?Sized,
119    {
120        f(self)
121    }
122}
123
124#[cfg(feature = "std")]
125impl<T> Guarded<T> for std::cell::RefCell<T>
126{
127    type Guard<'a>
128        = std::cell::Ref<'a, T>
129    where
130        Self: 'a;
131    fn get<'a>(&'a self) -> Self::Guard<'a> { self.borrow() }
132}
133#[cfg(feature = "std")]
134impl<T> TryGuarded<T> for std::cell::RefCell<T>
135{
136    type Error<'a>
137        = std::cell::BorrowError
138    where
139        Self: 'a;
140    fn try_get<'a>(&'a self) -> Result<Self::Guard<'a>, Self::Error<'a>> { self.try_borrow() }
141}
142#[cfg(feature = "std")]
143impl<T> GuardedMut<T> for std::cell::RefCell<T>
144{
145    type GuardMut<'a>
146        = std::cell::RefMut<'a, T>
147    where
148        Self: 'a;
149    fn get_mut<'a>(&'a self) -> Self::GuardMut<'a> { self.borrow_mut() }
150}
151#[cfg(feature = "std")]
152impl<T> TryGuardedMut<T> for std::cell::RefCell<T>
153{
154    type Error<'a>
155        = std::cell::BorrowMutError
156    where
157        Self: 'a;
158    fn try_get_mut<'a>(&'a self) -> Result<Self::GuardMut<'a>, Self::Error<'a>>
159    {
160        self.try_borrow_mut()
161    }
162}
163
164#[cfg(feature = "std")]
165impl<T> Guarded<T> for std::sync::Mutex<T>
166{
167    type Guard<'a>
168        = std::sync::MutexGuard<'a, T>
169    where
170        Self: 'a;
171    fn get<'a>(&'a self) -> Self::Guard<'a> { self.lock().expect("poisoned") }
172}
173#[cfg(feature = "std")]
174impl<T> TryGuarded<T> for std::sync::Mutex<T>
175{
176    type Error<'a>
177        = std::sync::PoisonError<std::sync::MutexGuard<'a, T>>
178    where
179        Self: 'a;
180    fn try_get<'a>(&'a self) -> Result<Self::Guard<'a>, Self::Error<'a>> { self.lock() }
181}
182#[cfg(feature = "std")]
183impl<T> GuardedMut<T> for std::sync::Mutex<T>
184{
185    type GuardMut<'a>
186        = std::sync::MutexGuard<'a, T>
187    where
188        Self: 'a;
189    fn get_mut<'a>(&'a self) -> Self::GuardMut<'a> { self.lock().expect("poisoned") }
190}
191#[cfg(feature = "std")]
192impl<T> TryGuardedMut<T> for std::sync::Mutex<T>
193{
194    type Error<'a>
195        = std::sync::PoisonError<std::sync::MutexGuard<'a, T>>
196    where
197        Self: 'a;
198    fn try_get_mut<'a>(&'a self) -> Result<Self::GuardMut<'a>, Self::Error<'a>> { self.lock() }
199}
200
201#[cfg(feature = "std")]
202impl<T> Guarded<T> for std::sync::RwLock<T>
203{
204    type Guard<'a>
205        = std::sync::RwLockReadGuard<'a, T>
206    where
207        Self: 'a;
208    fn get<'a>(&'a self) -> Self::Guard<'a> { self.read().expect("poisoned") }
209}
210#[cfg(feature = "std")]
211impl<T> TryGuarded<T> for std::sync::RwLock<T>
212{
213    type Error<'a>
214        = std::sync::PoisonError<std::sync::RwLockReadGuard<'a, T>>
215    where
216        Self: 'a;
217    fn try_get<'a>(&'a self) -> Result<Self::Guard<'a>, Self::Error<'a>> { self.read() }
218}
219#[cfg(feature = "std")]
220impl<T> GuardedMut<T> for std::sync::RwLock<T>
221{
222    type GuardMut<'a>
223        = std::sync::RwLockWriteGuard<'a, T>
224    where
225        Self: 'a;
226    fn get_mut<'a>(&'a self) -> Self::GuardMut<'a> { self.write().expect("poisoned") }
227}
228#[cfg(feature = "std")]
229impl<T> TryGuardedMut<T> for std::sync::RwLock<T>
230{
231    type Error<'a>
232        = std::sync::PoisonError<std::sync::RwLockWriteGuard<'a, T>>
233    where
234        Self: 'a;
235    fn try_get_mut<'a>(&'a self) -> Result<Self::GuardMut<'a>, Self::Error<'a>> { self.write() }
236}
237
238// TODO: impl it for SyncUnsafeCell<T> and all the std::sync::nonpoison::... type once they are stabilized
239
240#[cfg(feature = "std")]
241impl<'a, T: ?Sized> Guard<'a, T> for std::cell::Ref<'a, T>
242{
243    type Mapped<U>
244        = std::cell::Ref<'a, U>
245    where
246        U: 'a + ?Sized;
247    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
248    where
249        F: FnOnce(&T) -> &U,
250        U: 'a + ?Sized,
251    {
252        Self::map(self, f)
253    }
254}
255// Todo: impl Guard for RefMut when downgrade() will be available
256#[cfg(feature = "std")]
257impl<'a, T: ?Sized> GuardMut<'a, T> for std::cell::RefMut<'a, T>
258{
259    type MappedMut<U>
260        = std::cell::RefMut<'a, U>
261    where
262        U: 'a + ?Sized;
263    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
264    where
265        F: FnOnce(&mut T) -> &mut U,
266        U: 'a + ?Sized,
267    {
268        Self::map(self, f)
269    }
270}
271
272#[cfg(feature = "std")]
273impl<'a, T: ?Sized> Guard<'a, T> for std::sync::RwLockReadGuard<'a, T>
274{
275    type Mapped<U>
276        = std::sync::MappedRwLockReadGuard<'a, U>
277    where
278        U: 'a + ?Sized;
279    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
280    where
281        F: FnOnce(&T) -> &U,
282        U: 'a + ?Sized,
283    {
284        Self::map(self, f)
285    }
286}
287
288#[cfg(feature = "std")]
289impl<'a, T: ?Sized> Guard<'a, T> for std::sync::RwLockWriteGuard<'a, T>
290{
291    type Mapped<U>
292        = std::sync::MappedRwLockReadGuard<'a, U>
293    where
294        U: 'a + ?Sized;
295    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
296    where
297        F: FnOnce(&T) -> &U,
298        U: 'a + ?Sized,
299    {
300        Self::downgrade(self).guard_map(f)
301    }
302}
303#[cfg(feature = "std")]
304impl<'a, T: ?Sized> GuardMut<'a, T> for std::sync::RwLockWriteGuard<'a, T>
305{
306    type MappedMut<U>
307        = std::sync::MappedRwLockWriteGuard<'a, U>
308    where
309        U: 'a + ?Sized;
310    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
311    where
312        F: FnOnce(&mut T) -> &mut U,
313        U: 'a + ?Sized,
314    {
315        Self::map(self, f)
316    }
317}
318
319#[cfg(feature = "std")]
320impl<'a, T> Guard<'a, T> for std::sync::MappedRwLockReadGuard<'a, T>
321{
322    type Mapped<U>
323        = std::sync::MappedRwLockReadGuard<'a, U>
324    where
325        U: 'a + ?Sized;
326    fn guard_map<U, F>(self, f: F) -> Self::Mapped<U>
327    where
328        F: FnOnce(&T) -> &U,
329        U: 'a + ?Sized,
330    {
331        Self::map(self, f)
332    }
333}
334// Todo: impl Guard for MappedRwLockWriteGuard when downgrade() will be available
335#[cfg(feature = "std")]
336impl<'a, T> GuardMut<'a, T> for std::sync::MappedRwLockWriteGuard<'a, T>
337{
338    type MappedMut<U>
339        = std::sync::MappedRwLockWriteGuard<'a, U>
340    where
341        U: 'a + ?Sized;
342    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
343    where
344        F: FnOnce(&mut T) -> &mut U,
345        U: 'a + ?Sized,
346    {
347        Self::map(self, f)
348    }
349}
350
351#[cfg(feature = "std")]
352impl<'a, T> GuardMut<'a, T> for std::sync::MutexGuard<'a, T>
353{
354    type MappedMut<U>
355        = std::sync::MappedMutexGuard<'a, U>
356    where
357        U: 'a + ?Sized;
358    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
359    where
360        F: FnOnce(&mut T) -> &mut U,
361        U: 'a + ?Sized,
362    {
363        Self::map(self, f)
364    }
365}
366#[cfg(feature = "std")]
367impl<'a, T> GuardMut<'a, T> for std::sync::MappedMutexGuard<'a, T>
368{
369    type MappedMut<U>
370        = std::sync::MappedMutexGuard<'a, U>
371    where
372        U: 'a + ?Sized;
373    fn guard_map_mut<U, F>(self, f: F) -> Self::MappedMut<U>
374    where
375        F: FnOnce(&mut T) -> &mut U,
376        U: 'a + ?Sized,
377    {
378        Self::map(self, f)
379    }
380}