lib.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. pub struct SpecsUnit;
  2. impl<'a> specs::SystemData<'a> for SpecsUnit {
  3. fn setup(_world: &mut specs::World) {
  4. }
  5. fn fetch(_world: &'a specs::World) -> Self {
  6. SpecsUnit
  7. }
  8. fn reads() -> Vec<specs::prelude::ResourceId> {
  9. Vec::new()
  10. }
  11. fn writes() -> Vec<specs::prelude::ResourceId> {
  12. Vec::new()
  13. }
  14. }
  15. #[macro_export]
  16. macro_rules! system {
  17. ($name:ident ( $($pat:tt)* ) { $($rest:tt)* } ) => {
  18. pub struct $name;
  19. impl<'a> specs::System<'a> for $name {
  20. type SystemData = args_to_systemdata!(($($pat)*,));
  21. fn run(&mut self, args_to_fn_pat!(($($pat)*)): Self::SystemData) {
  22. for args_to_join_pat!(($($pat)*,)) in args_to_join!(($($pat)*,)).join() {
  23. $($rest)*
  24. }
  25. }
  26. }
  27. };
  28. ($name:ident $pat:tt { $($rest:tt)* } finally { $($finally:tt)* }) => {
  29. pub struct $name;
  30. impl<'a> specs::System<'a> for $name {
  31. type SystemData = args_to_systemdata!($pat);
  32. fn run(&mut self, args_to_fn_pat!($pat): Self::SystemData) {
  33. for args_to_join_pat!($pat) in args_to_join!($pat).join() {
  34. $($rest)*
  35. }
  36. $($finally)*
  37. }
  38. }
  39. };
  40. }
  41. #[macro_export]
  42. macro_rules! args_to_systemdata {
  43. ( ( ) ) => { crate::SpecsUnit };
  44. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  45. ( specs::ReadStorage<'a, $ty> ,)
  46. };
  47. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  48. ( specs::WriteStorage<'a, $ty> ,)
  49. };
  50. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  51. ( specs::ReadStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  52. };
  53. ( ( mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  54. ( specs::WriteStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  55. };
  56. ( ( resource $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  57. ( specs::ReadExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  58. };
  59. ( ( resource mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  60. ( specs::WriteExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  61. };
  62. }
  63. #[macro_export]
  64. macro_rules! args_to_fn_pat {
  65. ( ( ) ) => { _ };
  66. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  67. ( $name ,)
  68. };
  69. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  70. ( mut $name ,)
  71. };
  72. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  73. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  74. };
  75. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  76. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  77. };
  78. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  79. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  80. };
  81. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  82. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  83. };
  84. }
  85. #[macro_export]
  86. macro_rules! args_to_join_pat {
  87. ( ( ) ) => { _ };
  88. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  89. ( $name ,)
  90. };
  91. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  92. ( mut $name ,)
  93. };
  94. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  95. ( $name, args_to_join_pat!( ( $($tok)* ) ) )
  96. };
  97. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  98. ( mut $name, args_to_join_pat!( ( $($tok)* ) ) )
  99. };
  100. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  101. args_to_join_pat!( ( $($tok)* ) )
  102. };
  103. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  104. args_to_join_pat!( ( $($tok)* ) )
  105. };
  106. }
  107. #[macro_export]
  108. macro_rules! args_to_join {
  109. ( ( ) ) => { crate::SpecsUnit };
  110. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  111. ( & $name ,)
  112. };
  113. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  114. ( &mut $name ,)
  115. };
  116. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  117. ( & $name, args_to_join!( ( $($tok)* ) ) )
  118. };
  119. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  120. ( &mut $name, args_to_join!( ( $($tok)* ) ) )
  121. };
  122. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  123. args_to_join!( ( $($tok)* ) )
  124. };
  125. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  126. args_to_join!( ( $($tok)* ) )
  127. };
  128. }
  129. #[cfg(test)]
  130. mod tests {
  131. use specs::join::Join;
  132. pub struct Pos {
  133. x: usize,
  134. }
  135. impl specs::Component for Pos {
  136. type Storage = specs::VecStorage<Pos>;
  137. }
  138. pub struct Mov;
  139. impl specs::Component for Mov {
  140. type Storage = specs::VecStorage<Mov>;
  141. }
  142. system! {
  143. Foo (_x: Mov, mut y: Pos) {
  144. y.x += 1;
  145. }
  146. }
  147. system! {
  148. Bar (_x: Mov, mut y: Pos) {
  149. y.x += 1;
  150. } finally {
  151. println!("Done!");
  152. }
  153. }
  154. system! {
  155. Baz (resource n: usize, _x: Mov, mut y: Pos) {
  156. y.x += *n;
  157. }
  158. }
  159. system! {
  160. Quux (resource mut n: usize, _x: Mov, mut y: Pos) {
  161. y.x += *n;
  162. *n += 1
  163. }
  164. }
  165. }