1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
//! This crate defines the [`ComponentGroup`] trait.
//! This trait is used to make managing a group of [`specs::Component`] instances easier.
//! This is useful for when you have several components that are often created, read, and updated
//! together. You can use this trait to easily move an entire group of components between instances
//! of [`specs::World`].
//!
//! This crate also provides a custom derive (documented below) that you can use to automatically
//! implement the trait. This removes any of the boilerplate you may have needed to write in order
//! to implement the trait yourself and makes modifying your group of components much easier.
//!
//! ```rust,no_run
//! // Don't forget to add the component_group crate to your Cargo.toml file!
//! use component_group::ComponentGroup;
//! # use specs::{World, Component, VecStorage, HashMapStorage};
//! # use specs_derive::Component;
//!
//! // These components are just for demonstration purposes. You should swap them
//! // out for your own.
//!
//! // Components need to implement Clone to use the automatic derive.
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Position {x: i32, y: i32}
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Velocity {x: i32, y: i32}
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Health(u32);
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(HashMapStorage)]
//! pub struct Animation {frame: usize}
//!
//! // This is all of the code you need to write to define the group and its operations!
//! #[derive(ComponentGroup)]
//! struct PlayerComponents {
//!     position: Position,
//!     velocity: Velocity,
//!     health: Health,
//!     // This optional component is allowed to not be present
//!     animation: Option<Animation>,
//! }
//!
//! // Now you can easily add all of these components to an entity, load them all
//! // from the world, or even update them all at once!
//! ```
//!
//! See the documentation for [`ComponentGroup`] for the exact operations you can now perform on
//! the `PlayerComponents` struct. The rest of the documentation below goes into the motivation
//! behind this crate and details about how to use it.
//!
//! # Table of Contents
//!
//! * [Motivation](#motivation)
//! * [Manually Implementing `ComponentGroup`](#manually-implementing-componentgroup)
//! * [Automatically Implementing `ComponentGroup`](#automatically-implementing-componentgroup)
//! * [Optional Components](#optional-components)
//! * [Fetching Multiple Component Group Instances](#fetching-multiple-component-group-instances)
//! * [Generic Component Groups](#generic-component-groups)
//!
//! # Motivation
//!
//! The [`ComponentGroup`] trait makes operating on many components at once much easier and less
//! error-prone. Trying to update all of your code every time you add a new component to an entity
//! is very difficult to manage. By grouping all of the components together in a single struct, you
//! can better manage all of them and make fewer mistakes when you edit your code. The following is
//! an example of what your code might look like *without* this trait.
//!
//! ```rust
//! // Rust 2018 edition
//! use specs::{World, WorldExt, Builder, Entity, Component, VecStorage, ReadStorage, WriteStorage, Join};
//! use specs::error::Error as SpecsError;
//! use specs_derive::Component;
//!
//! // Let's setup some components to add to our World
//! #[derive(Debug, Component)]
//! #[storage(VecStorage)]
//! pub struct Position {x: i32, y: i32}
//!
//! #[derive(Debug, Component)]
//! #[storage(VecStorage)]
//! pub struct Velocity {x: i32, y: i32}
//!
//! #[derive(Debug, Component)]
//! #[storage(VecStorage)]
//! pub struct Health(u32);
//!
//! # use specs::Entities;
//! # fn find_player_entity(world: &World) -> Entity {
//! #     world.system_data::<Entities>().join().next().unwrap() // cheat since only one entity
//! # }
//! #
//! fn main() -> Result<(), SpecsError> {
//!     // Start the player on level 1
//!     let mut level1 = World::new();
//!     # level1.register::<Position>(); level1.register::<Velocity>(); level1.register::<Health>();
//!     // Add the player to the level
//!     level1.create_entity()
//!         // This player only has three components right now, but imagine what could happen
//!         // to this code as that number grows
//!         .with(Position {x: 12, y: 59})
//!         .with(Velocity {x: -1, y: 2})
//!         .with(Health(5))
//!         .build();
//!
//!     // ...
//!
//!     // Player needs to move on to the next level
//!     let mut level2 = World::new();
//!     # level2.register::<Position>(); level2.register::<Velocity>(); level2.register::<Health>();
//!     # { // Need to do this in its own scope (not relevant to the example)
//!     // Somehow find the player in the world it was just in
//!     let player_entity = find_player_entity(&level1);
//!     // Need to fetch all the components of the player. Be careful to keep this in sync with
//!     // the code above!
//!     let (positions, velocities, healths) = level1.system_data::<(
//!         ReadStorage<Position>,
//!         ReadStorage<Velocity>,
//!         ReadStorage<Health>,
//!     )>();
//!     // If any of these fields were Clone, we could call Option::cloned on the result
//!     // of `get(entity)` and avoid some of this boilerplate
//!     let position = positions.get(player_entity).map(|pos| Position {x: pos.x, y: pos.y})
//!         .expect("expected a Position component to be present");
//!     let velocity = velocities.get(player_entity).map(|vel| Velocity {x: vel.x, y: vel.y})
//!         .expect("expected a Velocity component to be present");
//!     let health = healths.get(player_entity).map(|health| Health(health.0))
//!         .expect("expected a Health component to be present");
//!     // Now we can add everything to the new level we created
//!     level2.create_entity()
//!         .with(position)
//!         .with(velocity)
//!         .with(health)
//!         .build();
//!     # } // Need to do this in its own scope (not relevant to the example)
//!
//!     // ...
//!
//!     // Player needs to go back to previous level
//!     // Find the player in level **2**
//!     let player_entity = find_player_entity(&level2);
//!     // That means that we need to now duplicate everything from above again!
//!     // This time we're fetching from level2, not level1
//!     let (positions, velocities, healths) = level2.system_data::<(
//!         ReadStorage<Position>,
//!         ReadStorage<Velocity>,
//!         ReadStorage<Health>,
//!     )>();
//!     let position = positions.get(player_entity).map(|pos| Position {x: pos.x, y: pos.y})
//!         .expect("expected a Position component to be present");
//!     let velocity = velocities.get(player_entity).map(|vel| Velocity {x: vel.x, y: vel.y})
//!         .expect("expected a Velocity component to be present");
//!     let health = healths.get(player_entity).map(|health| Health(health.0))
//!         .expect("expected a Health component to be present");
//!     // Now that we have the components, we need to re-add them to level **1** for the right
//!     // entity.
//!     let player_entity = find_player_entity(&level1);
//!     // Now we need to fetch write storages for every component, essentially duplicating the
//!     // code again! This time making sure we get the storages in level **1**
//!     let (mut positions, mut velocities, mut healths) = level1.system_data::<(
//!         WriteStorage<Position>,
//!         WriteStorage<Velocity>,
//!         WriteStorage<Health>,
//!     )>();
//!
//!     positions.insert(player_entity, position)?;
//!     velocities.insert(player_entity, velocity)?;
//!     healths.insert(player_entity, health)?;
//!
//!     Ok(())
//! }
//! ```
//!
//! There is a lot of duplication in this code! Many of the duplicated pieces of code have slight
//! differences like which world the components are being fetched from or whether we wanted
//! a `ReadStorage` or a `WriteStorage`.The purpose of this crate is to take all of that
//! duplication and make reusable methods that operate on all of the components at once.
//!
//! Instead of having to keep track of all of this code throughout your codebase, implementing the
//! `ComponentGroup` trait puts it all in one place. This makes updating your group much less
//! error-prone because adding/modifying/removing a component to/from the group only requires
//! modifying one area of code.
//!
//! The code that needs to be written to operate on all of these components together is
//! unavoidable given the API that specs provides, but at least you can make it easier by using
//! this crate. We've eliminated the need to write most of the repetitive code you saw above by
//! allowing you to automatically derive the `ComponentGroup` trait. All you need to do is define
//! the components in the group and everything else is generated for you.
//!
//! The next section of the documentation shows you how to manually implement the [`ComponentGroup`]
//! trait for a given group of components. This is still a lot of boilerplate, but it is all
//! grouped in one place. The section after that shows how to remove all the boilerplate by
//! automatically deriving the trait.
//!
//! # Manually Implementing `ComponentGroup`
//!
//! This example is meant to show what manually implementing this trait can be like. The basic idea
//! is to move all of the duplicated code from above into reusable methods on a struct that groups
//! all of the components that need to be modified together. Implementing it manually like this is
//! still quite cumbersome, so a way to automatically derive the trait is also provided. See below
//! for more details about that.
//!
//! ```rust
//! // Rust 2018 edition
//! // Don't forget to add component_group as a dependency to your Cargo.toml file!
//! use component_group::ComponentGroup;
//! use specs::{World, WorldExt, Builder, Entity, Entities, Component, VecStorage, ReadStorage, WriteStorage, Join};
//! use specs::error::Error as SpecsError;
//! use specs_derive::Component;
//!
//! // The one benefit of implementing the trait manually is that you don't need to make the
//! // fields Clone like you do when automatically deriving the trait.
//! #[derive(Debug, Component)]
//! #[storage(VecStorage)]
//! pub struct Position {x: i32, y: i32}
//!
//! #[derive(Debug, Component)]
//! #[storage(VecStorage)]
//! pub struct Velocity {x: i32, y: i32}
//!
//! #[derive(Debug, Component)]
//! #[storage(VecStorage)]
//! pub struct Health(u32);
//!
//! pub struct PlayerComponents {
//!     position: Position,
//!     velocity: Velocity,
//!     health: Health,
//! }
//!
//! impl ComponentGroup for PlayerComponents {
//!     type UpdateError = SpecsError;
//!
//!     fn first_from_world(world: &World) -> Option<(Entity, Self)> {
//!         // Needs to be updated every time the struct changes
//!         let (entities, positions, velocities, healths) = world.system_data::<(
//!             Entities,
//!             ReadStorage<Position>,
//!             ReadStorage<Velocity>,
//!             ReadStorage<Health>,
//!         )>();
//!         (&entities, &positions, &velocities, &healths).join().next()
//!             .map(|(entity, pos, vel, health)| (entity, Self {
//!                 // No need to clone because we know and can access all the fields
//!                 position: Position {x: pos.x, y: pos.y},
//!                 velocity: Velocity {x: vel.x, y: vel.y},
//!                 health: Health(health.0),
//!             }))
//!     }
//!
//!     fn from_world(world: &World, entity: Entity) -> Self {
//!         // Needs to be updated every time the struct changes
//!         let (positions, velocities, healths) = world.system_data::<(
//!             ReadStorage<Position>,
//!             ReadStorage<Velocity>,
//!             ReadStorage<Health>,
//!         )>();
//!         Self {
//!             // If any of these fields were Clone, we could call Option::cloned on the result
//!             // of `get(entity)` and avoid some of this boilerplate
//!             position: positions.get(entity).map(|pos| Position {x: pos.x, y: pos.y})
//!                 .expect("expected a Position component to be present"),
//!             velocity: velocities.get(entity).map(|vel| Velocity {x: vel.x, y: vel.y})
//!                 .expect("expected a Velocity component to be present"),
//!             health: healths.get(entity).map(|health| Health(health.0))
//!                 .expect("expected a Health component to be present"),
//!         }
//!     }
//!
//!     fn create(self, world: &mut World) -> Entity {
//!         // It's possible to write this code so that the compiler will at the very least
//!         // warn you if you forget one of the things you need to change when the struct
//!         // changes.
//!
//!         // Using pattern matching here forces a compiler error whenever the struct changes
//!         let Self {position, velocity, health} = self;
//!
//!         // Forgetting to add a .with() call will cause an unused variable warning
//!         world.create_entity()
//!             .with(position)
//!             .with(velocity)
//!             .with(health)
//!             .build()
//!     }
//!
//!     fn update(self, world: &mut World, entity: Entity) -> Result<(), Self::UpdateError> {
//!         // Needs to be updated every time the struct changes
//!         let (mut positions, mut velocities, mut healths) = world.system_data::<(
//!             WriteStorage<Position>,
//!             WriteStorage<Velocity>,
//!             WriteStorage<Health>,
//!         )>();
//!
//!         positions.insert(entity, self.position)?;
//!         velocities.insert(entity, self.velocity)?;
//!         healths.insert(entity, self.health)?;
//!         Ok(())
//!     }
//!
//!     fn remove(world: &mut World, entity: Entity) -> Self {
//!         // Needs to be updated every time the struct changes
//!         let (mut positions, mut velocities, mut healths) = world.system_data::<(
//!             WriteStorage<Position>,
//!             WriteStorage<Velocity>,
//!             WriteStorage<Health>,
//!         )>();
//!         Self {
//!             // If any of these fields were Clone, we could call Option::cloned on the result
//!             // of `get(entity)` and avoid some of this boilerplate
//!             position: positions.remove(entity).map(|pos| Position {x: pos.x, y: pos.y})
//!                 .expect("expected a Position component to be present"),
//!             velocity: velocities.remove(entity).map(|vel| Velocity {x: vel.x, y: vel.y})
//!                 .expect("expected a Velocity component to be present"),
//!             health: healths.remove(entity).map(|health| Health(health.0))
//!                 .expect("expected a Health component to be present"),
//!         }
//!     }
//! }
//!
//! # fn find_player_entity(world: &World) -> Entity {
//! #     world.system_data::<Entities>().join().next().unwrap() // cheat since only one entity
//! # }
//! #
//! fn main() -> Result<(), SpecsError> {
//!     // Start the player on level 1
//!     let mut level1 = World::new();
//!     # level1.register::<Position>(); level1.register::<Velocity>(); level1.register::<Health>();
//!     // Having all the components together in a struct means that Rust will enforce that you
//!     // never forget a field.
//!     // That being said, it is still possible to forget to add a component to the group. Adding
//!     // a component to the code above can be tricky and easy to mess up, but if you
//!     // automatically derive the trait, adding a component can be just a one-line change.
//!     let player = PlayerComponents {
//!         position: Position {x: 12, y: 59},
//!         velocity: Velocity {x: -1, y: 2},
//!         health: Health(5),
//!     };
//!     // Add the player to the level
//!     player.create(&mut level1);
//!
//!     // ...
//!
//!     // Player needs to move on to the next level
//!     let mut level2 = World::new();
//!     # level2.register::<Position>(); level2.register::<Velocity>(); level2.register::<Health>();
//!     // Somehow find the player in the world it was just in
//!     let player_entity = find_player_entity(&level1);
//!     // Extract the player from the world it was just in
//!     let player = PlayerComponents::from_world(&level1, player_entity);
//!     // Add it to the next world since it hasn't been added yet
//!     player.create(&mut level2);
//!
//!     // ...
//!
//!     // Player needs to go back to previous level
//!     // Using first_from_world is safe when you know that there is only one entity with all
//!     // the components in the group
//!     let (_, player) = PlayerComponents::first_from_world(&level2).unwrap();
//!     let player_entity = find_player_entity(&level1);
//!     // Move the player back
//!     player.update(&mut level1, player_entity)?;
//!
//!     Ok(())
//! }
//! ```
//!
//! # Automatically Implementing `ComponentGroup`
//!
//! You can also automatically implement the [`ComponentGroup`] trait using `#[derive(ComponentGroup)]`.
//! This removes all the boilerplate you saw in the example above and automatically provides each
//! of the methods in [`ComponentGroup`]. All fields in the struct must implement `Clone` so that
//! they can be copied within the methods that get implemented.
//!
//! ```rust
//! // Rust 2018 edition
//! use component_group::ComponentGroup;
//! use specs::{World, WorldExt, Component, VecStorage};
//! use specs::error::Error as SpecsError;
//! use specs_derive::Component;
//!
//! // Note that components need to be Clone to use the automatic derive
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Position {x: i32, y: i32}
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Velocity {x: i32, y: i32}
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Health(u32);
//!
//! // This is all of the code you need to write to define the group and all of its operations!
//! #[derive(ComponentGroup)]
//! struct PlayerComponents {
//!     position: Position,
//!     velocity: Velocity,
//!     health: Health,
//! }
//!
//! # fn find_player_entity(world: &World) -> specs::Entity {
//! #     use specs::{Entities, Join};
//! #     world.system_data::<Entities>().join().next().unwrap() // cheat since only one entity
//! # }
//! #
//! fn main() -> Result<(), SpecsError> {
//!     // Start the player on level 1
//!     let mut level1 = World::new();
//!     # level1.register::<Position>(); level1.register::<Velocity>(); level1.register::<Health>();
//!     // Having all the components together in a struct means that Rust will enforce that you
//!     // never forget a field. You can still forget to add a component to the group, but at
//!     // least that is just a one-line change thanks to the custom derive.
//!     let player = PlayerComponents {
//!         position: Position {x: 12, y: 59},
//!         velocity: Velocity {x: -1, y: 2},
//!         health: Health(5),
//!     };
//!     // Add the player to the level
//!     player.create(&mut level1);
//!
//!     // ...
//!
//!     // Player needs to move on to the next level
//!     let mut level2 = World::new();
//!     # level2.register::<Position>(); level2.register::<Velocity>(); level2.register::<Health>();
//!     // Somehow find the player in the world it was just in
//!     let player_entity = find_player_entity(&level1);
//!     // Extract the player from the world it was just in
//!     let player = PlayerComponents::from_world(&level1, player_entity);
//!     // Add it to the next world since it hasn't been added yet
//!     player.create(&mut level2);
//!
//!     // ...
//!
//!     // Player needs to go back to previous level
//!     // Using first_from_world is safe when you know that there is only one entity with all
//!     // the components in the group
//!     let (_, player) = PlayerComponents::first_from_world(&level2).unwrap();
//!     let player_entity = find_player_entity(&level1);
//!     // Move the player back
//!     player.update(&mut level1, player_entity)?;
//!
//!     Ok(())
//! }
//! ```
//!
//! # Optional Components
//!
//! You can also use `Option` to ignore part of the group if it isn't specified during creation or
//! if it isn't available in the `World` during extraction. If the field is `None`, a call to
//! `update` will remove that component for that entity from the component's storage.
//!
//! ```rust
//! # use component_group::ComponentGroup;
//! # use specs::{World, WorldExt, Component, VecStorage, HashMapStorage};
//! # use specs::error::Error as SpecsError;
//! # use specs_derive::Component;
//! # #[derive(Debug, Clone, Component)]
//! # #[storage(VecStorage)]
//! # pub struct Position {x: i32, y: i32}
//! #
//! # #[derive(Debug, Clone, Component)]
//! # #[storage(VecStorage)]
//! # pub struct Velocity {x: i32, y: i32}
//! #
//! # #[derive(Debug, Clone, Component)]
//! # #[storage(VecStorage)]
//! # pub struct Health(u32);
//! // (same components as before)
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(HashMapStorage)]
//! pub struct Animation {frame: usize}
//!
//! #[derive(ComponentGroup)]
//! struct PlayerComponents {
//!     position: Position,
//!     velocity: Velocity,
//!     health: Health,
//!     // This optional component is allowed to not be present
//!     animation: Option<Animation>,
//! }
//!
//! # fn find_player_entity(world: &World) -> specs::Entity {
//! #     use specs::{Entities, Join};
//! #     world.system_data::<Entities>().join().next().unwrap() // cheat since only one entity
//! # }
//! #
//! fn main() -> Result<(), SpecsError> {
//!     // Start the player on level 1
//!     let mut level1 = World::new();
//!     # level1.register::<Position>(); level1.register::<Velocity>(); level1.register::<Health>(); level1.register::<Animation>();
//!     let player = PlayerComponents {
//!         position: Position {x: 12, y: 59},
//!         velocity: Velocity {x: -1, y: 2},
//!         health: Health(5),
//!         // Since this field is None, the Animation component will not be added when the entity
//!         // is created
//!         animation: None, // Not animated to begin with
//!     };
//!     player.create(&mut level1);
//!
//!     // ...
//!
//!     // Player needs to move on to the next level
//!     let mut level2 = World::new();
//!     # level2.register::<Position>(); level2.register::<Velocity>(); level2.register::<Health>(); level2.register::<Animation>();
//!     // If an Animation component was added between the call to create() and this next call,
//!     // the field will be set to Some(animation_component) where animation_component is the
//!     // instance of the Animation component that was added. Otherwise, the field will be None.
//!     let player_entity = find_player_entity(&level1);
//!     let player = PlayerComponents::from_world(&level1, player_entity);
//!     player.create(&mut level2);
//!
//!     // ...
//!
//!     // Player needs to go back to previous level
//!     // The Animation component may have changed/added/removed, but we don't need to worry
//!     // about that here! The behaviour is the same as above.
//!     let (_, player) = PlayerComponents::first_from_world(&level2).unwrap();
//!     let player_entity = find_player_entity(&level1);
//!     // If the animation field is not None, we will call Storage::insert and add it to the
//!     // component's storage. Otherwise, we will call Storage::remove and get rid of it.
//!     player.update(&mut level1, player_entity)?;
//!
//!     Ok(())
//! }
//! ```
//!
//! **Note:** The way we match for the `Option` type is very naive right now. Using
//! `Option<YourComponent>` as the type of your field will work, but using
//! `std::option::Option<YourComponent>` will not.
//!
//! # Fetching Multiple Component Group Instances
//!
//! In the future, when [Generic Associated Types (GATs)] are implemented, this trait may be
//! updated as follows:
//!
//! ```rust,ignore
//! pub trait ComponentGroup: Sized {
//!     type UpdateError;
//!     type GroupIter<'a>;
//!
//!     // Extracts all instances of this group of components from the world.
//!     fn all_from_world<'a>(world: &'a World) -> Self::GroupIter<'a>;
//!     // ...other methods...
//! }
//! ```
//!
//! It just isn't possible to express this as part of the trait right now. Adding this would be a
//! breaking change, so that update would not occur without a new major version being released.
//!
//! As a workaround, you can add the method yourself using the impl Trait feature:
//!
//! ```rust,no_run
//! # use component_group::ComponentGroup;
//! # use specs::{World, WorldExt, Component, VecStorage, ReadStorage};
//! # use specs::error::Error as SpecsError;
//! # use specs_derive::Component;
//! #
//! # #[derive(Debug, Clone, Component)]
//! # #[storage(VecStorage)]
//! # pub struct Position {x: i32, y: i32}
//! #
//! # #[derive(Debug, Clone, Component)]
//! # #[storage(VecStorage)]
//! # pub struct Velocity {x: i32, y: i32}
//! #
//! # #[derive(Debug, Clone, Component)]
//! # #[storage(VecStorage)]
//! # pub struct Health(u32);
//! #
//! #[derive(ComponentGroup)]
//! struct PlayerComponents {
//!     position: Position,
//!     velocity: Velocity,
//!     health: Health,
//! }
//!
//! impl PlayerComponents {
//!     pub fn all_from_world<'a>(world: &'a World) -> impl Iterator<Item=Self> + 'a {
//!         // ...implement this...
//!         # (0..).map(|_| unimplemented!())
//!     }
//! }
//!
//! fn main() {
//!     let mut level1 = World::new();
//!     // ...do stuff...
//!
//!     for group in PlayerComponents::all_from_world(&level1) {
//!         // ...do stuff with each group...
//!     }
//! }
//! ```
//!
//! # Generic Component Groups
//!
//! It is possible to use the [`ComponentGroup`] trait and custom derive with generic structs. Just
//! make sure to add `Send + Sync + Component + Clone` trait bounds to the generic type parameters
//! or you will get a compile error. (The `Send + Sync` part is required by the `specs` crate.)
//!
//! ```rust,no_run
//! # use component_group::ComponentGroup;
//! # use specs::{World, Component, VecStorage, ReadStorage};
//! # use specs::error::Error as SpecsError;
//! # use specs_derive::Component;
//! #
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Position {x: i32, y: i32}
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct Velocity {x: i32, y: i32}
//!
//! #[derive(Debug, Clone, Component)]
//! #[storage(VecStorage)]
//! pub struct AngularVelocity {deg: f64}
//!
//! // Don't forget the trait bounds!
//! #[derive(ComponentGroup)]
//! struct PlayerComponents<V: Send + Sync + Component + Clone> {
//!     position: Position,
//!     velocity: V,
//! }
//!
//! // Can use this to provide different component groups that share most of their structure
//! type RunningPlayer = PlayerComponents<Velocity>;
//! type SpinningPlayer = PlayerComponents<AngularVelocity>;
//! #
//! # fn main() {
//! #     // Need to use the type aliases for them to be checked
//! #     let runner: RunningPlayer = unimplemented!();
//! #     let spinner: SpinningPlayer = unimplemented!();
//! # }
//! ```
//!
//! [`ComponentGroup`]: trait.ComponentGroup.html
//! [`specs::Component`]: https://docs.rs/specs/*/specs/trait.Component.html
//! [`specs::World`]: https://docs.rs/specs/*/specs/world/struct.World.html
//! [Generic Associated Types (GATs)]: https://github.com/rust-lang/rust/issues/44265

#![deny(unused_must_use)]

#[doc(hidden)] pub use component_group_derive::*;

use specs::{World, Entity};

/// Represents a group of [`specs::Component`] fields that can be added or extracted from
/// a [`specs::World`].
///
/// To automatically derive this trait using `#[derive(ComponentGroup)]`, all components within
/// the group must implement the `Clone` trait.
///
/// See the [top-level crate documentation](index.html) for more details.
///
/// [`specs::Component`]: https://docs.rs/specs/*/specs/trait.Component.html
/// [`specs::World`]: https://docs.rs/specs/*/specs/world/struct.World.html
pub trait ComponentGroup: Sized {
    /// The error type from the [`update` method](#tymethod.update)
    type UpdateError;

    /// Extracts the first instance of this component group from the world.
    ///
    /// This method is convenient if you know that there is exactly one instance of a this group in
    /// the world.
    ///
    /// Returns `None` if any of the required fields could not be populated. Fields with an
    /// `Option` type will be set to `None` if their component could not be populated.
    fn first_from_world(world: &World) -> Option<(Entity, Self)>;

    /// Extracts this group of components for the given entity from the given world.
    ///
    /// Panics if one of the component fields could not be populated. This can happen if the
    /// component does not exist for this entity. If the field is an `Option` type, its value will
    /// be set to `None` instead of panicking.
    fn from_world(world: &World, entity: Entity) -> Self;

    /// Creates a new entity in the world and adds all the components from this group to that entity.
    ///
    /// Any fields with a value of `None` will not be added to the created entity.
    fn create(self, world: &mut World) -> Entity;

    /// Update the components of a given entity with all of the components from this group.
    ///
    /// Any fields with a value of `None` will be explicitly removed from the given entity.
    ///
    /// Note: Any additional components that the entity has other than the ones covered by
    /// the fields of this group will be left untouched.
    fn update(self, world: &mut World, entity: Entity) -> Result<(), Self::UpdateError>;

    /// Removes all the components from this group from their storages in the given world for the
    /// given entity. Returns the values of the removed components.
    ///
    /// Note: Any additional components that the entity has other than the ones covered by
    /// the fields of this group will be left untouched.
    ///
    /// Panics if one of the required component fields was not present for removal. If the field is
    /// an `Option` type, its value when returned will be set to `None` instead of panicking.
    fn remove(world: &mut World, entity: Entity) -> Self;
}