Async Entity Component System based on the ideas of specs (https://github.com/amethyst/specs)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
3.7 KiB

  1. use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator, Reducer, WithSetup};
  2. /* Reduce */
  3. pub struct Reduce<X, S, O> {
  4. iterator: X,
  5. identity: S,
  6. operation: O,
  7. }
  8. impl<X, S, O> Reduce<X, S, O> {
  9. pub fn new(iterator: X, identity: S, operation: O) -> Self {
  10. Self {
  11. iterator,
  12. identity,
  13. operation,
  14. }
  15. }
  16. }
  17. impl<'a, X, S, O> Driver<'a, X::Item> for Reduce<X, S, O>
  18. where
  19. X: ParallelIterator<'a>,
  20. S: Fn() -> X::Item + Clone + Send + 'a,
  21. O: Fn(X::Item, X::Item) -> X::Item + Clone + Send + 'a,
  22. {
  23. fn exec_with<E>(self, executor: E) -> E::Result
  24. where
  25. E: Executor<'a, X::Item>,
  26. {
  27. let iterator = self.iterator;
  28. let identity = self.identity;
  29. let operation = self.operation;
  30. let consumer = ReduceConsumer {
  31. identity,
  32. operation,
  33. };
  34. iterator.drive(executor, consumer)
  35. }
  36. }
  37. /* ReduceWith */
  38. pub struct ReduceWith<X, O> {
  39. iterator: X,
  40. operation: O,
  41. }
  42. impl<X, O> ReduceWith<X, O> {
  43. pub fn new(iterator: X, operation: O) -> Self {
  44. Self {
  45. iterator,
  46. operation,
  47. }
  48. }
  49. }
  50. impl<'a, X, O, T> Driver<'a, Option<T>> for ReduceWith<X, O>
  51. where
  52. X: ParallelIterator<'a, Item = T>,
  53. O: Fn(T, T) -> T + Clone + Send + 'a,
  54. T: Send + 'a,
  55. {
  56. fn exec_with<E>(self, executor: E) -> E::Result
  57. where
  58. E: Executor<'a, Option<X::Item>>,
  59. {
  60. let fold_op = self.operation.clone();
  61. let reduce_op = self.operation;
  62. self.iterator
  63. .fold(<_>::default, move |a, b| match a {
  64. Some(a) => Some(fold_op(a, b)),
  65. None => Some(b),
  66. })
  67. .reduce(<_>::default, move |a, b| match (a, b) {
  68. (Some(a), Some(b)) => Some(reduce_op(a, b)),
  69. (Some(v), None) | (None, Some(v)) => Some(v),
  70. (None, None) => None,
  71. })
  72. .exec_with(executor)
  73. }
  74. }
  75. /* ReduceConsumer */
  76. struct ReduceConsumer<S, O> {
  77. identity: S,
  78. operation: O,
  79. }
  80. impl<S, O> WithSetup for ReduceConsumer<S, O> {}
  81. impl<S, O> Clone for ReduceConsumer<S, O>
  82. where
  83. S: Clone,
  84. O: Clone,
  85. {
  86. fn clone(&self) -> Self {
  87. Self {
  88. identity: self.identity.clone(),
  89. operation: self.operation.clone(),
  90. }
  91. }
  92. }
  93. impl<S, O, T> Consumer<T> for ReduceConsumer<S, O>
  94. where
  95. S: Fn() -> T + Clone + Send,
  96. O: Fn(T, T) -> T + Clone + Send,
  97. T: Send,
  98. {
  99. type Folder = ReduceFolder<O, T>;
  100. type Reducer = Self;
  101. type Result = T;
  102. fn split(self) -> (Self, Self, Self::Reducer) {
  103. (self.clone(), self.clone(), self)
  104. }
  105. fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
  106. (self.clone(), self.clone(), self)
  107. }
  108. fn into_folder(self) -> Self::Folder {
  109. ReduceFolder {
  110. operation: self.operation,
  111. item: (self.identity)(),
  112. }
  113. }
  114. }
  115. impl<S, O, T> Reducer<T> for ReduceConsumer<S, O>
  116. where
  117. O: Fn(T, T) -> T,
  118. S: Fn() -> T,
  119. T: Send,
  120. {
  121. fn reduce(self, left: T, right: T) -> T {
  122. (self.operation)(left, right)
  123. }
  124. }
  125. /* ReduceFolder */
  126. struct ReduceFolder<O, T> {
  127. operation: O,
  128. item: T,
  129. }
  130. impl<O, T> Folder<T> for ReduceFolder<O, T>
  131. where
  132. O: Fn(T, T) -> T + Clone,
  133. {
  134. type Result = T;
  135. fn consume(mut self, item: T) -> Self {
  136. self.item = (self.operation)(self.item, item);
  137. self
  138. }
  139. fn consume_iter<X>(mut self, iter: X) -> Self
  140. where
  141. X: IntoIterator<Item = T>,
  142. {
  143. self.item = iter.into_iter().fold(self.item, self.operation.clone());
  144. self
  145. }
  146. fn complete(self) -> Self::Result {
  147. self.item
  148. }
  149. }