hala_ops/
deref.rs

1use std::{
2    cell::UnsafeCell,
3    ops::{self},
4};
5
6/// This trait extend [`Deref`](ops::Deref) to add function `deref_map`
7pub trait DerefExt: ops::Deref {
8    fn deref_map<F, R>(self, f: F) -> MapDeref<Self, F>
9    where
10        Self: Sized,
11        F: Fn(&Self::Target) -> &R,
12    {
13        MapDeref { deref: self, f }
14    }
15}
16
17/// The type map [`Deref`](ops::Deref) target to another type.
18pub struct MapDeref<T, F> {
19    deref: T,
20    f: F,
21}
22
23impl<T, F, R> ops::Deref for MapDeref<T, F>
24where
25    F: Fn(&T::Target) -> &R,
26    T: ops::Deref,
27{
28    type Target = R;
29
30    fn deref(&self) -> &Self::Target {
31        (self.f)(self.deref.deref())
32    }
33}
34
35/// Implement [`DerefExt`] for all type that implement trait [`Deref`](ops::Deref)
36impl<T> DerefExt for T where T: ops::Deref {}
37
38/// This trait extend [`DerefMut`](ops::DerefMut) to add function `deref_mut_map`
39pub trait DerefMutExt: ops::DerefMut {
40    fn deref_mut_map<F, R>(self, f: F) -> MapDerefMut<Self, F>
41    where
42        Self: Sized,
43        F: Fn(&mut Self::Target) -> &mut R,
44    {
45        MapDerefMut {
46            deref: UnsafeCell::new(self),
47            f,
48        }
49    }
50}
51
52/// The type map [`DerefMut`](ops::DerefMut)'s target to another type.
53pub struct MapDerefMut<T, F> {
54    deref: UnsafeCell<T>,
55    f: F,
56}
57
58impl<T, F, R> ops::Deref for MapDerefMut<T, F>
59where
60    F: Fn(&mut T::Target) -> &mut R,
61    T: ops::DerefMut,
62{
63    type Target = R;
64
65    fn deref(&self) -> &Self::Target {
66        // Safety: borrowing checks stil valid for [`MapDerefMut`]
67        (self.f)(unsafe { &mut *self.deref.get() })
68    }
69}
70
71impl<T, F, R> ops::DerefMut for MapDerefMut<T, F>
72where
73    F: Fn(&mut T::Target) -> &mut R,
74    T: ops::DerefMut,
75{
76    fn deref_mut(&mut self) -> &mut Self::Target {
77        // Safety: borrowing checks stil valid for [`MapDerefMut`]
78        (self.f)(unsafe { &mut *self.deref.get() })
79    }
80}
81
82/// Implement [`DerefMutExt`] for all type that implement trait [`DerefMut`](ops::DerefMut)
83impl<T> DerefMutExt for T where T: ops::DerefMut {}