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.

173 line
3.8 KiB

  1. use std::iter::Zip;
  2. use std::ops::Range;
  3. use crate::{
  4. Consumer, Executor, ExecutorCallback, IndexedParallelIterator, IndexedProducer,
  5. IndexedProducerCallback, ParallelIterator, Producer, Reducer, Setup, WithIndexedProducer,
  6. WithSetup,
  7. };
  8. pub struct Enumerate<X> {
  9. base: X,
  10. }
  11. impl<X> Enumerate<X> {
  12. pub fn new(base: X) -> Self {
  13. Self { base }
  14. }
  15. }
  16. impl<'a, X, I> ParallelIterator<'a> for Enumerate<X>
  17. where
  18. X: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>,
  19. I: Send + 'a,
  20. {
  21. type Item = (usize, I);
  22. fn drive<E, C, D, R>(self, executor: E, consumer: C) -> E::Result
  23. where
  24. E: Executor<'a, D>,
  25. C: Consumer<Self::Item, Result = D, Reducer = R> + 'a,
  26. D: Send + 'a,
  27. R: Reducer<D> + Send + 'a,
  28. {
  29. self.with_indexed_producer(ExecutorCallback::new(executor, consumer))
  30. }
  31. fn len_hint_opt(&self) -> Option<usize> {
  32. self.base.len_hint_opt()
  33. }
  34. }
  35. impl<'a, X, I> IndexedParallelIterator<'a> for Enumerate<X>
  36. where
  37. X: IndexedParallelIterator<'a, Item = I> + WithIndexedProducer<'a, Item = I>,
  38. I: Send + 'a,
  39. {
  40. fn drive_indexed<E, C, D, R>(self, executor: E, consumer: C) -> E::Result
  41. where
  42. E: Executor<'a, D>,
  43. C: Consumer<Self::Item, Result = D, Reducer = R> + 'a,
  44. D: Send + 'a,
  45. R: Reducer<D> + Send + 'a,
  46. {
  47. self.with_indexed_producer(ExecutorCallback::new(executor, consumer))
  48. }
  49. fn len_hint(&self) -> usize {
  50. self.base.len_hint()
  51. }
  52. }
  53. impl<'a, X> WithIndexedProducer<'a> for Enumerate<X>
  54. where
  55. X: WithIndexedProducer<'a>,
  56. {
  57. type Item = (usize, X::Item);
  58. fn with_indexed_producer<CB>(self, base: CB) -> CB::Output
  59. where
  60. CB: IndexedProducerCallback<'a, Self::Item>,
  61. {
  62. self.base.with_indexed_producer(EnumerateCallback { base })
  63. }
  64. }
  65. /* EnumerateCallback */
  66. struct EnumerateCallback<CB> {
  67. base: CB,
  68. }
  69. impl<'a, CB, I> IndexedProducerCallback<'a, I> for EnumerateCallback<CB>
  70. where
  71. CB: IndexedProducerCallback<'a, (usize, I)>,
  72. {
  73. type Output = CB::Output;
  74. fn callback<P>(self, base: P) -> Self::Output
  75. where
  76. P: IndexedProducer<Item = I> + 'a,
  77. {
  78. self.base.callback(EnumerateProducer { base, offset: 0 })
  79. }
  80. }
  81. /* EnumerateProducer */
  82. struct EnumerateProducer<P> {
  83. base: P,
  84. offset: usize,
  85. }
  86. impl<P> WithSetup for EnumerateProducer<P>
  87. where
  88. P: WithSetup,
  89. {
  90. fn setup(&self) -> Setup {
  91. self.base.setup()
  92. }
  93. }
  94. impl<P> Producer for EnumerateProducer<P>
  95. where
  96. P: IndexedProducer,
  97. {
  98. type Item = (usize, P::Item);
  99. type IntoIter = Zip<Range<usize>, P::IntoIter>;
  100. fn into_iter(self) -> Self::IntoIter {
  101. let base = self.base.into_iter();
  102. let start = self.offset;
  103. let end = start + base.len();
  104. (start..end).zip(base)
  105. }
  106. fn split(self) -> (Self, Option<Self>) {
  107. let len = self.base.len();
  108. if len < 2 {
  109. return (self, None);
  110. }
  111. let (left, right) = self.split_at(len / 2);
  112. (left, Some(right))
  113. }
  114. }
  115. impl<P> IndexedProducer for EnumerateProducer<P>
  116. where
  117. P: IndexedProducer,
  118. {
  119. type Item = (usize, P::Item);
  120. type IntoIter = Zip<Range<usize>, P::IntoIter>;
  121. fn into_iter(self) -> Self::IntoIter {
  122. let base = self.base.into_iter();
  123. let start = self.offset;
  124. let end = start + base.len();
  125. (start..end).zip(base)
  126. }
  127. fn len(&self) -> usize {
  128. self.base.len()
  129. }
  130. fn split_at(self, index: usize) -> (Self, Self) {
  131. let (left, right) = self.base.split_at(index);
  132. let left = Self {
  133. base: left,
  134. offset: self.offset,
  135. };
  136. let right = Self {
  137. base: right,
  138. offset: self.offset + index,
  139. };
  140. (left, right)
  141. }
  142. }