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.

135 lines
5.6 KiB

  1. use super::{Folder, WithSetup};
  2. /// A variant on `Producer` which does not know its exact length or
  3. /// cannot represent it in a `usize`. These producers act like
  4. /// ordinary producers except that they cannot be told to split at a
  5. /// particular point. Instead, you just ask them to split 'somewhere'.
  6. ///
  7. /// (In principle, `Producer` could extend this trait; however, it
  8. /// does not because to do so would require producers to carry their
  9. /// own length with them.)
  10. pub trait Producer: WithSetup + Send + Sized {
  11. /// The type of item returned by this producer.
  12. type Item;
  13. /// The type of iterator we will become.
  14. type IntoIter: Iterator<Item = Self::Item>;
  15. /// Convert `self` into an iterator; at this point, no more parallel splits
  16. /// are possible.
  17. fn into_iter(self) -> Self::IntoIter;
  18. /// Split midway into a new producer if possible, otherwise return `None`.
  19. fn split(self) -> (Self, Option<Self>);
  20. /// Iterate the producer, feeding each element to `folder`, and
  21. /// stop when the folder is full (or all elements have been consumed).
  22. ///
  23. /// The provided implementation is sufficient for most iterables.
  24. fn fold_with<F>(self, folder: F) -> F
  25. where
  26. F: Folder<Self::Item>,
  27. {
  28. folder.consume_iter(self.into_iter())
  29. }
  30. }
  31. /// A `Producer` is effectively a "splittable `IntoIterator`". That
  32. /// is, a producer is a value which can be converted into an iterator
  33. /// at any time: at that point, it simply produces items on demand,
  34. /// like any iterator. But what makes a `Producer` special is that,
  35. /// *before* we convert to an iterator, we can also **split** it at a
  36. /// particular point using the `split_at` method. This will yield up
  37. /// two producers, one producing the items before that point, and one
  38. /// producing the items after that point (these two producers can then
  39. /// independently be split further, or be converted into iterators).
  40. /// In Rayon, this splitting is used to divide between threads.
  41. /// See [the `plumbing` README][r] for further details.
  42. ///
  43. /// Note that each producer will always produce a fixed number of
  44. /// items N. However, this number N is not queryable through the API;
  45. /// the consumer is expected to track it.
  46. ///
  47. /// NB. You might expect `Producer` to extend the `IntoIterator`
  48. /// trait. However, [rust-lang/rust#20671][20671] prevents us from
  49. /// declaring the DoubleEndedIterator and ExactSizeIterator
  50. /// constraints on a required IntoIterator trait, so we inline
  51. /// IntoIterator here until that issue is fixed.
  52. ///
  53. /// [r]: https://github.com/rayon-rs/rayon/blob/master/src/iter/plumbing/README.md
  54. /// [20671]: https://github.com/rust-lang/rust/issues/20671
  55. #[allow(clippy::len_without_is_empty)]
  56. pub trait IndexedProducer: WithSetup + Send + Sized {
  57. /// The type of item that will be produced by this producer once
  58. /// it is converted into an iterator.
  59. type Item;
  60. /// The type of iterator we will become.
  61. type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator + ExactSizeIterator;
  62. /// Convert `self` into an iterator; at this point, no more parallel splits
  63. /// are possible.
  64. fn into_iter(self) -> Self::IntoIter;
  65. /// Produces an exact count of how many items this producer will
  66. /// emit, presuming no panic occurs.
  67. fn len(&self) -> usize;
  68. /// Split into two producers; one produces items `0..index`, the
  69. /// other `index..N`. Index must be less than or equal to `N`.
  70. fn split_at(self, index: usize) -> (Self, Self);
  71. /// Iterate the producer, feeding each element to `folder`, and
  72. /// stop when the folder is full (or all elements have been consumed).
  73. ///
  74. /// The provided implementation is sufficient for most iterables.
  75. fn fold_with<F>(self, folder: F) -> F
  76. where
  77. F: Folder<Self::Item>,
  78. {
  79. folder.consume_iter(self.into_iter())
  80. }
  81. }
  82. /// The `ProducerCallback` trait is a kind of generic closure,
  83. /// [analogous to `FnOnce`][FnOnce]. See [the corresponding section in
  84. /// the plumbing README][r] for more details.
  85. ///
  86. /// [r]: https://github.com/rayon-rs/rayon/blob/master/src/iter/plumbing/README.md#producer-callback
  87. /// [FnOnce]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html
  88. pub trait ProducerCallback<'p, I> {
  89. /// The type of value returned by this callback. Analogous to
  90. /// [`Output` from the `FnOnce` trait][Output].
  91. ///
  92. /// [Output]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html#associatedtype.Output
  93. type Output;
  94. /// Invokes the callback with the given producer as argument. The
  95. /// key point of this trait is that this method is generic over
  96. /// `P`, and hence implementors must be defined for any producer.
  97. fn callback<P>(self, producer: P) -> Self::Output
  98. where
  99. P: Producer<Item = I> + 'p;
  100. }
  101. /// The `IndexedProducerCallback` trait is a kind of generic closure,
  102. /// [analogous to `FnOnce`][FnOnce]. See [the corresponding section in
  103. /// the plumbing README][r] for more details.
  104. ///
  105. /// [r]: https://github.com/rayon-rs/rayon/blob/master/src/iter/plumbing/README.md#producer-callback
  106. /// [FnOnce]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html
  107. pub trait IndexedProducerCallback<'p, I> {
  108. /// The type of value returned by this callback. Analogous to
  109. /// [`Output` from the `FnOnce` trait][Output].
  110. ///
  111. /// [Output]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html#associatedtype.Output
  112. type Output;
  113. /// Invokes the callback with the given producer as argument. The
  114. /// key point of this trait is that this method is generic over
  115. /// `P`, and hence implementors must be defined for any producer.
  116. fn callback<P>(self, producer: P) -> Self::Output
  117. where
  118. P: IndexedProducer<Item = I> + 'p;
  119. }