1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
use gc_arena::{Collect, MutationContext}; use crate::{ flatten::Flatten, map::{Map, MapWith}, then::{Then, ThenWith}, Sequence, }; /// Extension trait for `Sequence` that provides useful combinator methods. pub trait SequenceExt<'gc>: Sized + Sequence<'gc> { /// Map a function over result of this sequence. /// /// The given function is run in the same call to `Sequence::step` that produces the result of /// this sequence. fn map<F, R>(self, f: F) -> Map<Self, F> where F: 'static + FnOnce(Self::Output) -> R, { Map::new(self, f) } /// Equivalent to `SequencExt::map` but calls the function with a context parameter. /// /// The context parameter can be anything that implements `Collect`. It exists to allow /// closures to manually close over variables that implement `Collect`, because there is no way /// currently for closure types to automatically implement `Collect` and are thus required to be /// 'static. fn map_with<C, F, R>(self, c: C, f: F) -> MapWith<Self, C, F> where C: Collect, F: 'static + FnOnce(C, Self::Output) -> R, { MapWith::new(self, c, f) } /// Execute a separate sequence step after this sequence completes. /// /// The given function is run in a separate `Sequence::step` call from the one that produces the /// result of this sequence. fn then<F, R>(self, f: F) -> Then<'gc, Self, F> where Self::Output: Collect, F: 'static + FnOnce(MutationContext<'gc, '_>, Self::Output) -> R, { Then::new(self, f) } /// Equivalent to `SequenceExt::then` but calls the function with the given context parameter. /// /// The context parameter can be anything that implements `Collect`, it exists to allow closures /// to manually close over variables that implement `Collect`, because there is no way currently /// for closure types to automatically themselves implement `Collect` and are thus required to /// be 'static. fn then_with<C, F, R>(self, c: C, f: F) -> ThenWith<'gc, Self, C, F> where C: Collect, Self::Output: Collect, F: 'static + FnOnce(MutationContext<'gc, '_>, C, Self::Output) -> R, { ThenWith::new(self, c, f) } /// Call a function on the result of this sequence, producing a new sequence to run. /// /// The given function is run in a separate `Sequence::step` call to the one that produces a /// result of this sequence, and the `Sequence` that this function results in is run in /// additional separate `Sequence::step` calls. fn chain<F, R>(self, f: F) -> Flatten<'gc, Then<'gc, Self, F>> where Self::Output: Collect, F: 'static + FnOnce(MutationContext<'gc, '_>, Self::Output) -> R, R: Sequence<'gc>, { Flatten::new(Then::new(self, f)) } /// Equivalent to `SequenceExt::chain` but calls the function with the given context parameter. /// /// The context parameter can be anything that implements `Collect`, it exists to allow closures /// to manually close over variables that implement `Collect`, because there is no way currently /// for closure types to automatically themselves implement `Collect` and are thus required to /// be 'static. fn chain_with<C, F, R>(self, c: C, f: F) -> Flatten<'gc, ThenWith<'gc, Self, C, F>> where C: Collect, Self::Output: Collect, F: 'static + FnOnce(MutationContext<'gc, '_>, C, Self::Output) -> R, R: Sequence<'gc>, { Flatten::new(ThenWith::new(self, c, f)) } /// If this sequence results in another sequence, this combinator flattens them so that they are /// executed one after another. fn flatten(self) -> Flatten<'gc, Self> where Self::Output: Sequence<'gc>, { Flatten::new(self) } /// Turn this sequence into a boxed sequence type. /// /// The return type is a `dyn Sequence` because where you would need to produce a boxed sequence /// you generally are doing this to purposefully forget what the particular sequence type is, /// and doing this here eases type inference. fn boxed(self) -> Box<dyn Sequence<'gc, Output = Self::Output> + 'gc> where Self: 'gc, { Box::new(self) } } impl<'gc, T> SequenceExt<'gc> for T where T: Sequence<'gc> {}