1
- use std:: { marker:: PhantomData , ops:: Deref } ;
1
+ use std:: {
2
+ any:: Any ,
3
+ hash:: { Hash , Hasher } ,
4
+ marker:: PhantomData ,
5
+ ops:: Deref ,
6
+ } ;
2
7
8
+ use crate :: { DatabaseDyn , DerivedNodeId , ParamId , dependency:: NodeKind } ;
3
9
use intern:: InternId ;
4
10
5
- use crate :: { DatabaseDyn , DerivedNodeId , ParamId , dependency:: NodeKind } ;
11
+ type MemoRefProjectorStep = for <' a > fn ( & ' a dyn Any ) -> & ' a dyn Any ;
12
+
13
+ const MAX_PROJECTOR_STEPS : usize = 4 ;
14
+
15
+ #[ inline( always) ]
16
+ fn step_identity ( value : & dyn Any ) -> & dyn Any {
17
+ value
18
+ }
19
+
20
+ #[ inline( always) ]
21
+ fn step_result_ok < T : ' static , E : ' static > ( value : & dyn Any ) -> & dyn Any {
22
+ match value
23
+ . downcast_ref :: < Result < T , E > > ( )
24
+ . expect ( "MemoRef<Result<..>>: underlying value has unexpected type" )
25
+ {
26
+ Ok ( t) => t as & dyn Any ,
27
+ Err ( _) => unreachable ! ( "Ok projection used only after Ok check" ) ,
28
+ }
29
+ }
30
+
31
+ #[ inline( always) ]
32
+ fn step_option_some < T : ' static > ( value : & dyn Any ) -> & dyn Any {
33
+ match value
34
+ . downcast_ref :: < Option < T > > ( )
35
+ . expect ( "MemoRef<Option<..>>: underlying value has unexpected type" )
36
+ {
37
+ Some ( t) => t as & dyn Any ,
38
+ None => unreachable ! ( "Some projection used only after Some check" ) ,
39
+ }
40
+ }
41
+
42
+ #[ inline( always) ]
43
+ fn step_tuple_0 < T0 : ' static , T1 : ' static > ( value : & dyn Any ) -> & dyn Any {
44
+ let ( t0, _) = value
45
+ . downcast_ref :: < ( T0 , T1 ) > ( )
46
+ . expect ( "MemoRef<(..)>: underlying value has unexpected type" ) ;
47
+ t0 as & dyn Any
48
+ }
49
+
50
+ #[ inline( always) ]
51
+ fn step_tuple_1 < T0 : ' static , T1 : ' static > ( value : & dyn Any ) -> & dyn Any {
52
+ let ( _, t1) = value
53
+ . downcast_ref :: < ( T0 , T1 ) > ( )
54
+ . expect ( "MemoRef<(..)>: underlying value has unexpected type" ) ;
55
+ t1 as & dyn Any
56
+ }
6
57
7
58
#[ derive( Debug ) ]
8
59
pub struct MemoRef < T > {
9
60
pub ( crate ) db : * const dyn DatabaseDyn ,
10
61
pub ( crate ) derived_node_id : DerivedNodeId ,
62
+ projectors : [ MemoRefProjectorStep ; MAX_PROJECTOR_STEPS ] ,
63
+ projectors_len : u8 ,
11
64
phantom : PhantomData < T > ,
12
65
}
13
66
@@ -27,12 +80,23 @@ impl<T> PartialEq for MemoRef<T> {
27
80
28
81
impl < T > Eq for MemoRef < T > { }
29
82
83
+ #[ allow( clippy:: unnecessary_cast) ]
84
+ impl < T > Hash for MemoRef < T > {
85
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
86
+ let data_ptr = self . db as * const dyn DatabaseDyn as * const ( ) ;
87
+ data_ptr. hash ( state) ;
88
+ self . derived_node_id . hash ( state) ;
89
+ }
90
+ }
91
+
30
92
#[ allow( clippy:: unnecessary_cast) ]
31
93
impl < T : ' static + Clone > MemoRef < T > {
32
94
pub fn new ( db : & dyn DatabaseDyn , derived_node_id : DerivedNodeId ) -> Self {
33
95
Self {
34
96
db : db as * const _ as * const dyn DatabaseDyn ,
35
97
derived_node_id,
98
+ projectors : [ step_identity; MAX_PROJECTOR_STEPS ] ,
99
+ projectors_len : 0 ,
36
100
phantom : PhantomData ,
37
101
}
38
102
}
@@ -63,6 +127,83 @@ impl<T: 'static> Deref for MemoRef<T> {
63
127
NodeKind :: Derived ( self . derived_node_id ) ,
64
128
revision. time_updated ,
65
129
) ;
66
- value. downcast_ref :: < T > ( ) . unwrap ( )
130
+ let mut any_ref: & dyn Any = value;
131
+ let len = self . projectors_len as usize ;
132
+ for step in & self . projectors [ ..len] {
133
+ any_ref = ( step) ( any_ref) ;
134
+ }
135
+ any_ref
136
+ . downcast_ref :: < T > ( )
137
+ . expect ( "MemoRef: projector chain produced unexpected type" )
138
+ }
139
+ }
140
+
141
+ impl < T : ' static , E : ' static + Clone > MemoRef < Result < T , E > > {
142
+ pub fn try_ok ( self ) -> Result < MemoRef < T > , E > {
143
+ match self . deref ( ) {
144
+ Ok ( _) => {
145
+ let mut next = MemoRef :: < T > {
146
+ db : self . db ,
147
+ derived_node_id : self . derived_node_id ,
148
+ projectors : self . projectors ,
149
+ projectors_len : self . projectors_len ,
150
+ phantom : PhantomData ,
151
+ } ;
152
+ let idx = next. projectors_len as usize ;
153
+ next. projectors [ idx] = step_result_ok :: < T , E > ;
154
+ next. projectors_len += 1 ;
155
+ Ok ( next)
156
+ }
157
+ Err ( err) => Err ( err. clone ( ) ) ,
158
+ }
159
+ }
160
+ }
161
+
162
+ impl < T : ' static > MemoRef < Option < T > > {
163
+ pub fn try_some ( self ) -> Option < MemoRef < T > > {
164
+ match self . deref ( ) {
165
+ Some ( _) => {
166
+ let mut next = MemoRef :: < T > {
167
+ db : self . db ,
168
+ derived_node_id : self . derived_node_id ,
169
+ projectors : self . projectors ,
170
+ projectors_len : self . projectors_len ,
171
+ phantom : PhantomData ,
172
+ } ;
173
+ let idx = next. projectors_len as usize ;
174
+ next. projectors [ idx] = step_option_some :: < T > ;
175
+ next. projectors_len += 1 ;
176
+ Some ( next)
177
+ }
178
+ None => None ,
179
+ }
180
+ }
181
+ }
182
+
183
+ impl < T0 : ' static , T1 : ' static > MemoRef < ( T0 , T1 ) > {
184
+ pub fn split ( self ) -> ( MemoRef < T0 > , MemoRef < T1 > ) {
185
+ let mut left = MemoRef :: < T0 > {
186
+ db : self . db ,
187
+ derived_node_id : self . derived_node_id ,
188
+ projectors : self . projectors ,
189
+ projectors_len : self . projectors_len ,
190
+ phantom : PhantomData ,
191
+ } ;
192
+ let idx = left. projectors_len as usize ;
193
+ left. projectors [ idx] = step_tuple_0 :: < T0 , T1 > ;
194
+ left. projectors_len += 1 ;
195
+
196
+ let mut right = MemoRef :: < T1 > {
197
+ db : self . db ,
198
+ derived_node_id : self . derived_node_id ,
199
+ projectors : self . projectors ,
200
+ projectors_len : self . projectors_len ,
201
+ phantom : PhantomData ,
202
+ } ;
203
+ let idx = right. projectors_len as usize ;
204
+ right. projectors [ idx] = step_tuple_1 :: < T0 , T1 > ;
205
+ right. projectors_len += 1 ;
206
+
207
+ ( left, right)
67
208
}
68
209
}
0 commit comments