cfx_storage/utils/
deref_plus_impl_or_borrow_self.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5/// The trait automatically implements for D: Deref with D::Target. User may add
6/// implementation of DerefPlusSelf<Target = Type> for some Type
7/// via enable_deref_for_self, where Type can be str, \[T\], or a local type
8/// (i.e. not an upstream type).
9pub trait DerefPlusSelf {
10    type Target: ?Sized;
11
12    fn deref(&self) -> &Self::Target;
13}
14
15pub trait DerefMutPlusSelf {
16    type Target: ?Sized;
17
18    fn deref_mut(&mut self) -> &mut Self::Target;
19}
20
21/// We can not impl DerefPlusSelf automatically for a general T because it
22/// would conflict with the blanket implementation for D: Deref below, because
23/// the compiler can not rule out the possibility for D: Deref + Sized with
24/// D::Target == D. For a local type, compiler will first check if Deref is
25/// implemented for that type, and if D::Target == D.
26macro_rules! enable_deref_for_self {
27    ($type:ty) => {
28        impl DerefPlusSelf for $type {
29            type Target = Self;
30
31            fn deref(&self) -> &Self { self }
32        }
33        impl DerefMutPlusSelf for $type {
34            type Target = Self;
35
36            fn deref_mut(&mut self) -> &mut Self { self }
37        }
38    };
39}
40
41impl<D: Deref<Target = T>, T: ?Sized> DerefPlusSelf for D {
42    type Target = T;
43
44    fn deref(&self) -> &T { Deref::deref(self) }
45}
46
47impl<D: DerefMut<Target = T>, T: ?Sized> DerefMutPlusSelf for D {
48    type Target = T;
49
50    fn deref_mut(&mut self) -> &mut T { DerefMut::deref_mut(self) }
51}
52
53/// This trait is automatically implemented for the Trait ifself, any type which
54/// implements Trait, and any Borrow of the Trait.
55pub trait ImplOrBorrowSelf<Trait: ?Sized> {
56    fn borrow(&self) -> &Trait;
57}
58
59/// This trait is automatically implemented for the Trait ifself, any type which
60/// implements Trait, and any BorrowMut of the Trait.
61pub trait ImplOrBorrowMutSelf<Trait: ?Sized> {
62    fn borrow_mut(&mut self) -> &mut Trait;
63}
64
65/// Suppose you have a trait Trait and some type T: Trait, this trait is
66/// automatically implemented for Trait itself, &Tr, `Box<Tr>`, `Arc<Tr>`, &T,
67/// `Box<T>`, `Arc<T>`, etc. When DerefPlusSelf is implemented for T, this trait
68/// is also implemented for T.
69pub trait DerefPlusImplOrBorrowSelf<T: ?Sized> {
70    fn borrow(&self) -> &T;
71}
72
73pub trait DerefMutPlusImplOrBorrowMutSelf<T: ?Sized> {
74    fn borrow_mut(&mut self) -> &mut T;
75}
76
77/// We can not impl DerefPlusImplOrBorrowSelf automatically for a general Trait
78/// because it would conflict with the blanket implementation for D:
79/// DerefPlusSelf,
80///
81/// For trait, they are !Sized so compiler knows for sure that implementation
82/// for D isn't possible.
83macro_rules! enable_deref_plus_impl_or_borrow_self {
84    ($trait:path) => {
85        impl<'a> ImplOrBorrowSelf<dyn 'a + $trait> for dyn 'a + $trait {
86            fn borrow(&self) -> &(dyn 'a + $trait) { self }
87        }
88
89        impl<'a> ImplOrBorrowSelf<dyn 'a + $trait> for &(dyn 'a + $trait) {
90            fn borrow(&self) -> &(dyn 'a + $trait) { *self }
91        }
92
93        impl<'a, T: 'a + $trait> ImplOrBorrowSelf<dyn 'a + $trait> for T {
94            fn borrow(&self) -> &(dyn 'a + $trait) { self }
95        }
96
97        impl<'a> DerefPlusImplOrBorrowSelf<dyn 'a + $trait>
98            for dyn 'a + $trait
99        {
100            fn borrow(&self) -> &(dyn 'a + $trait) { self }
101        }
102
103        impl<
104                'a,
105                D: DerefPlusSelf<Target = T>,
106                T: 'a + ImplOrBorrowSelf<dyn 'a + $trait> + ?Sized,
107            > DerefPlusImplOrBorrowSelf<dyn 'a + $trait> for D
108        {
109            fn borrow(&self) -> &(dyn 'a + $trait) {
110                <T as ImplOrBorrowSelf<dyn 'a + $trait>>::borrow(self.deref())
111            }
112        }
113    };
114}
115
116macro_rules! enable_deref_mut_plus_impl_or_borrow_mut_self {
117    ($trait:path) => {
118        impl<'a> ImplOrBorrowMutSelf<dyn 'a + $trait> for dyn 'a + $trait {
119            fn borrow_mut(&mut self) -> &mut (dyn 'a + $trait) { self }
120        }
121
122        impl<'a> ImplOrBorrowMutSelf<dyn 'a + $trait>
123            for &mut (dyn 'a + $trait)
124        {
125            fn borrow_mut(&mut self) -> &mut (dyn 'a + $trait) { *self }
126        }
127
128        impl<'a, T: 'a + $trait> ImplOrBorrowMutSelf<dyn 'a + $trait> for T {
129            fn borrow_mut(&mut self) -> &mut (dyn 'a + $trait) { self }
130        }
131
132        impl<'a> DerefMutPlusImplOrBorrowMutSelf<dyn 'a + $trait>
133            for dyn 'a + $trait
134        {
135            fn borrow_mut(&mut self) -> &mut (dyn 'a + $trait) { self }
136        }
137
138        impl<
139                'a,
140                D: DerefMutPlusSelf<Target = T>,
141                T: 'a + ImplOrBorrowMutSelf<dyn 'a + $trait> + ?Sized,
142            > DerefMutPlusImplOrBorrowMutSelf<dyn 'a + $trait> for D
143        {
144            fn borrow_mut(&mut self) -> &mut (dyn 'a + $trait) {
145                <T as ImplOrBorrowMutSelf<dyn 'a + $trait>>::borrow_mut(
146                    self.deref_mut(),
147                )
148            }
149        }
150    };
151}
152
153#[cfg(test)]
154mod test {
155    use super::*;
156
157    enable_deref_for_self!(str);
158    enable_deref_for_self!([u8]);
159    enable_deref_for_self!(my_vec::MyVec<u8>);
160
161    enable_deref_plus_impl_or_borrow_self!(TestTrait);
162    enable_deref_for_self!(Test);
163
164    trait TestTrait {
165        fn print(&self, x: i32) {
166            println!("{}", x);
167        }
168    }
169    struct Test {}
170    mod my_vec {
171        #[allow(dead_code)]
172        pub struct MyVec<T>(#[allow(unused)] pub Vec<T>);
173    }
174
175    impl TestTrait for Test {}
176
177    /// Don't run, just check for compilation.
178    #[allow(unused)]
179    fn test<'a>(x: &'a i32) {
180        let test = Test {};
181        <Test as DerefPlusImplOrBorrowSelf<dyn TestTrait>>::borrow(&test)
182            .print(*x);
183        <&Test as DerefPlusImplOrBorrowSelf<dyn TestTrait>>::borrow(&&test)
184            .print(*x);
185        let boxed: Box<dyn 'a + TestTrait> = Box::new(test);
186        <dyn 'a + TestTrait as DerefPlusImplOrBorrowSelf<dyn 'a + TestTrait>>::borrow(
187            Deref::deref(&boxed),
188        )
189        .print(*x);
190        <&(dyn 'a + TestTrait) as DerefPlusImplOrBorrowSelf<
191            dyn 'a + TestTrait,
192        >>::borrow(&Deref::deref(&boxed))
193        .print(*x);
194        <Box<dyn 'a + TestTrait> as DerefPlusImplOrBorrowSelf<
195            dyn 'a + TestTrait,
196        >>::borrow(&boxed)
197        .print(*x);
198    }
199}
200
201use std::ops::{Deref, DerefMut};