@@ -11,25 +11,53 @@ struct PluginEntry {
11
11
enabled : bool ,
12
12
}
13
13
14
+ /// Builds and customizes a plugin group. A plugin group is an ordered list of plugins that
15
+ /// that can be enabled, disabled or reordered.
14
16
#[ derive( Default ) ]
15
17
pub struct PluginGroupBuilder {
16
18
plugins : HashMap < TypeId , PluginEntry > ,
17
19
order : Vec < TypeId > ,
18
20
}
19
21
20
22
impl PluginGroupBuilder {
23
+ // Removes a previous ordering of a plugin that has just been added at `added_at` index
24
+ fn remove_when_adding < T : Plugin > ( & mut self , added_at : usize ) {
25
+ if let Some ( to_remove) = self
26
+ . order
27
+ . iter ( )
28
+ . enumerate ( )
29
+ . find ( |( i, ty) | * i != added_at && * * ty == TypeId :: of :: < T > ( ) )
30
+ . map ( |( i, _) | i)
31
+ {
32
+ self . order . remove ( to_remove) ;
33
+ }
34
+ }
35
+
36
+ /// Adds the plugin `plugin` at the end of this `PluginGroupBuilder`. If the plugin was
37
+ /// already in the group, it is removed from its previous place.
21
38
pub fn add < T : Plugin > ( & mut self , plugin : T ) -> & mut Self {
39
+ let target_index = self . order . len ( ) ;
22
40
self . order . push ( TypeId :: of :: < T > ( ) ) ;
23
- self . plugins . insert (
24
- TypeId :: of :: < T > ( ) ,
25
- PluginEntry {
26
- plugin : Box :: new ( plugin) ,
27
- enabled : true ,
28
- } ,
29
- ) ;
41
+ if self
42
+ . plugins
43
+ . insert (
44
+ TypeId :: of :: < T > ( ) ,
45
+ PluginEntry {
46
+ plugin : Box :: new ( plugin) ,
47
+ enabled : true ,
48
+ } ,
49
+ )
50
+ . is_some ( )
51
+ {
52
+ self . remove_when_adding :: < T > ( target_index) ;
53
+ }
54
+
30
55
self
31
56
}
32
57
58
+ /// Adds the plugin `plugin` in this `PluginGroupBuilder` before the plugin of type `Target`.
59
+ /// If the plugin was already the group, it is removed from its previous place. There must
60
+ /// be a plugin of type `Target` in the group or it will fail.
33
61
pub fn add_before < Target : Plugin , T : Plugin > ( & mut self , plugin : T ) -> & mut Self {
34
62
let target_index = self
35
63
. order
@@ -44,16 +72,25 @@ impl PluginGroupBuilder {
44
72
)
45
73
} ) ;
46
74
self . order . insert ( target_index, TypeId :: of :: < T > ( ) ) ;
47
- self . plugins . insert (
48
- TypeId :: of :: < T > ( ) ,
49
- PluginEntry {
50
- plugin : Box :: new ( plugin) ,
51
- enabled : true ,
52
- } ,
53
- ) ;
75
+ if self
76
+ . plugins
77
+ . insert (
78
+ TypeId :: of :: < T > ( ) ,
79
+ PluginEntry {
80
+ plugin : Box :: new ( plugin) ,
81
+ enabled : true ,
82
+ } ,
83
+ )
84
+ . is_some ( )
85
+ {
86
+ self . remove_when_adding :: < T > ( target_index) ;
87
+ }
54
88
self
55
89
}
56
90
91
+ /// Adds the plugin `plugin` in this `PluginGroupBuilder` after the plugin of type `Target`.
92
+ /// If the plugin was already the group, it is removed from its previous place. There must
93
+ /// be a plugin of type `Target` in the group or it will fail.
57
94
pub fn add_after < Target : Plugin , T : Plugin > ( & mut self , plugin : T ) -> & mut Self {
58
95
let target_index = self
59
96
. order
@@ -66,18 +103,27 @@ impl PluginGroupBuilder {
66
103
"Plugin does not exist: {}." ,
67
104
std:: any:: type_name:: <Target >( )
68
105
)
69
- } ) ;
70
- self . order . insert ( target_index + 1 , TypeId :: of :: < T > ( ) ) ;
71
- self . plugins . insert (
72
- TypeId :: of :: < T > ( ) ,
73
- PluginEntry {
74
- plugin : Box :: new ( plugin) ,
75
- enabled : true ,
76
- } ,
77
- ) ;
106
+ } )
107
+ + 1 ;
108
+ self . order . insert ( target_index, TypeId :: of :: < T > ( ) ) ;
109
+ if self
110
+ . plugins
111
+ . insert (
112
+ TypeId :: of :: < T > ( ) ,
113
+ PluginEntry {
114
+ plugin : Box :: new ( plugin) ,
115
+ enabled : true ,
116
+ } ,
117
+ )
118
+ . is_some ( )
119
+ {
120
+ self . remove_when_adding :: < T > ( target_index) ;
121
+ }
78
122
self
79
123
}
80
124
125
+ /// Enables the plugin of type `T` in this `PluginGroupBuilder`. There must
126
+ /// be a plugin of type `Target` in the group or it will fail.
81
127
pub fn enable < T : Plugin > ( & mut self ) -> & mut Self {
82
128
let mut plugin_entry = self
83
129
. plugins
@@ -87,6 +133,10 @@ impl PluginGroupBuilder {
87
133
self
88
134
}
89
135
136
+ /// Disables the plugin of type `T` in this `PluginGroupBuilder`, but leave it in its
137
+ /// place so that you can still use [`add_before`](Self::add_before) or
138
+ /// [`add_after`](Self::add_after), or re-enable it with [`enable`](Self::enable).
139
+ /// There must be a plugin of type `Target` in the group or it will fail.
90
140
pub fn disable < T : Plugin > ( & mut self ) -> & mut Self {
91
141
let mut plugin_entry = self
92
142
. plugins
@@ -96,6 +146,7 @@ impl PluginGroupBuilder {
96
146
self
97
147
}
98
148
149
+ /// Adds the enabled [`Plugin`] from this group in order to the application.
99
150
pub fn finish ( self , app : & mut AppBuilder ) {
100
151
for ty in self . order . iter ( ) {
101
152
if let Some ( entry) = self . plugins . get ( ty) {
@@ -107,3 +158,135 @@ impl PluginGroupBuilder {
107
158
}
108
159
}
109
160
}
161
+
162
+ #[ cfg( test) ]
163
+ mod tests {
164
+ use super :: PluginGroupBuilder ;
165
+ use crate :: { AppBuilder , Plugin } ;
166
+
167
+ struct PluginA ;
168
+ impl Plugin for PluginA {
169
+ fn build ( & self , _: & mut AppBuilder ) {
170
+ ( )
171
+ }
172
+ }
173
+
174
+ struct PluginB ;
175
+ impl Plugin for PluginB {
176
+ fn build ( & self , _: & mut AppBuilder ) {
177
+ ( )
178
+ }
179
+ }
180
+
181
+ struct PluginC ;
182
+ impl Plugin for PluginC {
183
+ fn build ( & self , _: & mut AppBuilder ) {
184
+ ( )
185
+ }
186
+ }
187
+
188
+ #[ test]
189
+ fn basic_ordering ( ) {
190
+ let mut group = PluginGroupBuilder :: default ( ) ;
191
+ group. add ( PluginA ) ;
192
+ group. add ( PluginB ) ;
193
+ group. add ( PluginC ) ;
194
+
195
+ assert_eq ! (
196
+ group. order,
197
+ vec![
198
+ std:: any:: TypeId :: of:: <PluginA >( ) ,
199
+ std:: any:: TypeId :: of:: <PluginB >( ) ,
200
+ std:: any:: TypeId :: of:: <PluginC >( ) ,
201
+ ]
202
+ )
203
+ }
204
+
205
+ #[ test]
206
+ fn add_after ( ) {
207
+ let mut group = PluginGroupBuilder :: default ( ) ;
208
+ group. add ( PluginA ) ;
209
+ group. add ( PluginB ) ;
210
+ group. add_after :: < PluginA , PluginC > ( PluginC ) ;
211
+
212
+ assert_eq ! (
213
+ group. order,
214
+ vec![
215
+ std:: any:: TypeId :: of:: <PluginA >( ) ,
216
+ std:: any:: TypeId :: of:: <PluginC >( ) ,
217
+ std:: any:: TypeId :: of:: <PluginB >( ) ,
218
+ ]
219
+ )
220
+ }
221
+
222
+ #[ test]
223
+ fn add_before ( ) {
224
+ let mut group = PluginGroupBuilder :: default ( ) ;
225
+ group. add ( PluginA ) ;
226
+ group. add ( PluginB ) ;
227
+ group. add_before :: < PluginB , PluginC > ( PluginC ) ;
228
+
229
+ assert_eq ! (
230
+ group. order,
231
+ vec![
232
+ std:: any:: TypeId :: of:: <PluginA >( ) ,
233
+ std:: any:: TypeId :: of:: <PluginC >( ) ,
234
+ std:: any:: TypeId :: of:: <PluginB >( ) ,
235
+ ]
236
+ )
237
+ }
238
+
239
+ #[ test]
240
+ fn readd ( ) {
241
+ let mut group = PluginGroupBuilder :: default ( ) ;
242
+ group. add ( PluginA ) ;
243
+ group. add ( PluginB ) ;
244
+ group. add ( PluginC ) ;
245
+ group. add ( PluginB ) ;
246
+
247
+ assert_eq ! (
248
+ group. order,
249
+ vec![
250
+ std:: any:: TypeId :: of:: <PluginA >( ) ,
251
+ std:: any:: TypeId :: of:: <PluginC >( ) ,
252
+ std:: any:: TypeId :: of:: <PluginB >( ) ,
253
+ ]
254
+ )
255
+ }
256
+
257
+ #[ test]
258
+ fn readd_after ( ) {
259
+ let mut group = PluginGroupBuilder :: default ( ) ;
260
+ group. add ( PluginA ) ;
261
+ group. add ( PluginB ) ;
262
+ group. add ( PluginC ) ;
263
+ group. add_after :: < PluginA , PluginC > ( PluginC ) ;
264
+
265
+ assert_eq ! (
266
+ group. order,
267
+ vec![
268
+ std:: any:: TypeId :: of:: <PluginA >( ) ,
269
+ std:: any:: TypeId :: of:: <PluginC >( ) ,
270
+ std:: any:: TypeId :: of:: <PluginB >( ) ,
271
+ ]
272
+ )
273
+ }
274
+
275
+ #[ test]
276
+ fn readd_before ( ) {
277
+ let mut group = PluginGroupBuilder :: default ( ) ;
278
+ group. add ( PluginA ) ;
279
+ group. add ( PluginB ) ;
280
+ group. add ( PluginC ) ;
281
+ group. add_before :: < PluginB , PluginC > ( PluginC ) ;
282
+
283
+ assert_eq ! (
284
+ group. order,
285
+ vec![
286
+ std:: any:: TypeId :: of:: <PluginA >( ) ,
287
+ std:: any:: TypeId :: of:: <PluginC >( ) ,
288
+ std:: any:: TypeId :: of:: <PluginB >( ) ,
289
+ ]
290
+ )
291
+ }
292
+ }
0 commit comments