Async Entity Component System based on the ideas of specs (https://github.com/amethyst/specs)
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

416 líneas
9.2 KiB

  1. use std::marker::PhantomData;
  2. use crate::{
  3. misc::Try, Consumer, Executor, Folder, ParallelIterator, Producer, ProducerCallback, Reducer,
  4. Setup, WithProducer, WithSetup,
  5. };
  6. /* TryFold */
  7. pub struct TryFold<X, S, O, T> {
  8. base: X,
  9. init: S,
  10. operation: O,
  11. marker: PhantomData<T>,
  12. }
  13. impl<X, S, O, T> TryFold<X, S, O, T> {
  14. pub fn new(base: X, init: S, operation: O) -> Self {
  15. Self {
  16. base,
  17. init,
  18. operation,
  19. marker: PhantomData,
  20. }
  21. }
  22. }
  23. impl<'a, X, S, O, U, T> ParallelIterator<'a> for TryFold<X, S, O, T>
  24. where
  25. X: ParallelIterator<'a>,
  26. S: Fn() -> U + Clone + Send + 'a,
  27. O: Fn(U, X::Item) -> T + Clone + Send + 'a,
  28. U: Send,
  29. T: Try<Ok = U> + Send + 'a,
  30. {
  31. type Item = T;
  32. fn drive<E, C, D, R>(self, executor: E, consumer: C) -> E::Result
  33. where
  34. E: Executor<'a, D>,
  35. C: Consumer<Self::Item, Result = D, Reducer = R> + 'a,
  36. D: Send + 'a,
  37. R: Reducer<D> + Send + 'a,
  38. {
  39. self.base.drive(
  40. executor,
  41. TryFoldConsumer {
  42. base: consumer,
  43. init: self.init,
  44. operation: self.operation,
  45. marker: PhantomData,
  46. },
  47. )
  48. }
  49. }
  50. impl<'a, X, S, O, U, T> WithProducer<'a> for TryFold<X, S, O, T>
  51. where
  52. X: WithProducer<'a>,
  53. S: Fn() -> U + Clone + Send + 'a,
  54. O: Fn(U, X::Item) -> T + Clone + Send + 'a,
  55. U: Send,
  56. T: Try<Ok = U> + Send + 'a,
  57. {
  58. type Item = T;
  59. fn with_producer<CB>(self, callback: CB) -> CB::Output
  60. where
  61. CB: ProducerCallback<'a, Self::Item>,
  62. {
  63. self.base.with_producer(TryFoldCallback {
  64. base: callback,
  65. init: self.init,
  66. operation: self.operation,
  67. marker: PhantomData,
  68. })
  69. }
  70. }
  71. /* TryFoldWith */
  72. pub struct TryFoldWith<X, U, O, T> {
  73. base: X,
  74. init: U,
  75. operation: O,
  76. marker: PhantomData<T>,
  77. }
  78. impl<X, U, O, T> TryFoldWith<X, U, O, T> {
  79. pub fn new(base: X, init: U, operation: O) -> Self {
  80. Self {
  81. base,
  82. init,
  83. operation,
  84. marker: PhantomData,
  85. }
  86. }
  87. }
  88. impl<'a, X, U, O, T> ParallelIterator<'a> for TryFoldWith<X, U, O, T>
  89. where
  90. X: ParallelIterator<'a>,
  91. U: Clone + Send + 'a,
  92. O: Fn(U, X::Item) -> T + Clone + Send + 'a,
  93. T: Try<Ok = U> + Send + 'a,
  94. {
  95. type Item = T;
  96. fn drive<E, C, D, R>(self, executor: E, consumer: C) -> E::Result
  97. where
  98. E: Executor<'a, D>,
  99. C: Consumer<Self::Item, Result = D, Reducer = R> + 'a,
  100. D: Send + 'a,
  101. R: Reducer<D> + Send + 'a,
  102. {
  103. let TryFoldWith {
  104. base,
  105. init,
  106. operation,
  107. ..
  108. } = self;
  109. base.drive(
  110. executor,
  111. TryFoldConsumer {
  112. base: consumer,
  113. init: move || init.clone(),
  114. operation,
  115. marker: PhantomData,
  116. },
  117. )
  118. }
  119. }
  120. impl<'a, X, U, O, T> WithProducer<'a> for TryFoldWith<X, U, O, T>
  121. where
  122. X: WithProducer<'a>,
  123. U: Clone + Send + 'a,
  124. O: Fn(U, X::Item) -> T + Clone + Send + 'a,
  125. T: Try<Ok = U> + Send + 'a,
  126. {
  127. type Item = T;
  128. fn with_producer<CB>(self, callback: CB) -> CB::Output
  129. where
  130. CB: ProducerCallback<'a, Self::Item>,
  131. {
  132. let TryFoldWith {
  133. base,
  134. init,
  135. operation,
  136. ..
  137. } = self;
  138. base.with_producer(TryFoldCallback {
  139. base: callback,
  140. init: move || init.clone(),
  141. operation,
  142. marker: PhantomData,
  143. })
  144. }
  145. }
  146. /* TryFoldConsumer */
  147. struct TryFoldConsumer<C, S, O, T> {
  148. base: C,
  149. init: S,
  150. operation: O,
  151. marker: PhantomData<T>,
  152. }
  153. impl<C, S, O, T> WithSetup for TryFoldConsumer<C, S, O, T>
  154. where
  155. C: WithSetup,
  156. {
  157. fn setup(&self) -> Setup {
  158. self.base.setup()
  159. }
  160. }
  161. impl<'a, C, S, O, T, I> Consumer<I> for TryFoldConsumer<C, S, O, T>
  162. where
  163. C: Consumer<T>,
  164. S: Fn() -> T::Ok + Clone + Send,
  165. O: Fn(T::Ok, I) -> T + Clone + Send,
  166. T: Try + Send,
  167. {
  168. type Folder = TryFoldFolder<C::Folder, O, T>;
  169. type Reducer = C::Reducer;
  170. type Result = C::Result;
  171. fn split(self) -> (Self, Self, Self::Reducer) {
  172. let (left, right, reducer) = self.base.split();
  173. let left = TryFoldConsumer {
  174. base: left,
  175. init: self.init.clone(),
  176. operation: self.operation.clone(),
  177. marker: PhantomData,
  178. };
  179. let right = TryFoldConsumer {
  180. base: right,
  181. init: self.init,
  182. operation: self.operation,
  183. marker: PhantomData,
  184. };
  185. (left, right, reducer)
  186. }
  187. fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) {
  188. let (left, right, reducer) = self.base.split_at(index);
  189. let left = TryFoldConsumer {
  190. base: left,
  191. init: self.init.clone(),
  192. operation: self.operation.clone(),
  193. marker: PhantomData,
  194. };
  195. let right = TryFoldConsumer {
  196. base: right,
  197. init: self.init,
  198. operation: self.operation,
  199. marker: PhantomData,
  200. };
  201. (left, right, reducer)
  202. }
  203. fn into_folder(self) -> Self::Folder {
  204. TryFoldFolder {
  205. base: self.base.into_folder(),
  206. item: T::from_ok((self.init)()),
  207. operation: self.operation,
  208. }
  209. }
  210. fn is_full(&self) -> bool {
  211. self.base.is_full()
  212. }
  213. }
  214. /* TryFoldCallback */
  215. struct TryFoldCallback<CB, S, O, T> {
  216. base: CB,
  217. init: S,
  218. operation: O,
  219. marker: PhantomData<T>,
  220. }
  221. impl<'a, CB, S, O, T, I> ProducerCallback<'a, I> for TryFoldCallback<CB, S, O, T>
  222. where
  223. CB: ProducerCallback<'a, T>,
  224. S: Fn() -> T::Ok + Clone + Send + 'a,
  225. O: Fn(T::Ok, I) -> T + Clone + Send + 'a,
  226. T: Try + Send + 'a,
  227. {
  228. type Output = CB::Output;
  229. fn callback<P>(self, producer: P) -> Self::Output
  230. where
  231. P: Producer<Item = I> + 'a,
  232. {
  233. self.base.callback(TryFoldProducer {
  234. base: producer,
  235. init: self.init,
  236. operation: self.operation,
  237. marker: PhantomData,
  238. })
  239. }
  240. }
  241. /* TryFoldProducer */
  242. struct TryFoldProducer<P, S, O, T> {
  243. base: P,
  244. init: S,
  245. operation: O,
  246. marker: PhantomData<T>,
  247. }
  248. impl<P, S, O, T> WithSetup for TryFoldProducer<P, S, O, T>
  249. where
  250. P: WithSetup,
  251. {
  252. fn setup(&self) -> Setup {
  253. self.base.setup()
  254. }
  255. }
  256. impl<'a, P, S, O, T> Producer for TryFoldProducer<P, S, O, T>
  257. where
  258. P: Producer,
  259. S: Fn() -> T::Ok + Clone + Send,
  260. O: Fn(T::Ok, P::Item) -> T + Clone + Send,
  261. T: Try + Send,
  262. {
  263. type Item = T;
  264. type IntoIter = std::iter::Once<T>;
  265. fn into_iter(self) -> Self::IntoIter {
  266. let mut ret = T::from_ok((self.init)());
  267. for item in self.base.into_iter() {
  268. match ret.into_result() {
  269. Ok(value) => ret = (self.operation)(value, item),
  270. Err(err) => return std::iter::once(T::from_error(err)),
  271. }
  272. }
  273. std::iter::once(ret)
  274. }
  275. fn split(self) -> (Self, Option<Self>) {
  276. let init = self.init;
  277. let operation = self.operation;
  278. let (left, right) = self.base.split();
  279. let left = TryFoldProducer {
  280. base: left,
  281. init: init.clone(),
  282. operation: operation.clone(),
  283. marker: PhantomData,
  284. };
  285. let right = right.map(move |right| TryFoldProducer {
  286. base: right,
  287. init,
  288. operation,
  289. marker: PhantomData,
  290. });
  291. (left, right)
  292. }
  293. fn fold_with<F>(self, folder: F) -> F
  294. where
  295. F: Folder<Self::Item>,
  296. {
  297. self.base
  298. .fold_with(TryFoldFolder {
  299. base: folder,
  300. item: T::from_ok((self.init)()),
  301. operation: self.operation,
  302. })
  303. .base
  304. }
  305. }
  306. /* TryFoldFolder */
  307. struct TryFoldFolder<F, O, T> {
  308. base: F,
  309. operation: O,
  310. item: T,
  311. }
  312. impl<F, O, T, I> Folder<I> for TryFoldFolder<F, O, T>
  313. where
  314. F: Folder<T>,
  315. O: Fn(T::Ok, I) -> T + Clone,
  316. T: Try + Send,
  317. {
  318. type Result = F::Result;
  319. fn consume(mut self, item: I) -> Self {
  320. self.item = match self.item.into_result() {
  321. Ok(value) => (self.operation)(value, item),
  322. Err(err) => T::from_error(err),
  323. };
  324. self
  325. }
  326. fn consume_iter<X>(self, iter: X) -> Self
  327. where
  328. X: IntoIterator<Item = I>,
  329. {
  330. let TryFoldFolder {
  331. base,
  332. operation,
  333. mut item,
  334. } = self;
  335. for next in iter.into_iter() {
  336. if base.is_full() {
  337. break;
  338. }
  339. match item.into_result() {
  340. Ok(value) => item = operation(value, next),
  341. Err(err) => {
  342. item = T::from_error(err);
  343. break;
  344. }
  345. }
  346. }
  347. TryFoldFolder {
  348. base,
  349. operation,
  350. item,
  351. }
  352. }
  353. fn complete(self) -> Self::Result {
  354. self.base.consume(self.item).complete()
  355. }
  356. fn is_full(&self) -> bool {
  357. self.base.is_full()
  358. }
  359. }