windowed_stats/experimental/event/
reactor.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::experimental::clock::Timed;
6use crate::experimental::event::Event;
7
8/// A type that can be converted into a [`Reactor`].
9///
10/// This trait is notably implemented for collection types of [`Reactor`]s for chaining. For
11/// example, `IntoReactor` is implemented for tuples of [`Reactor`] types in [`ThenChain`] and so
12/// such tuples can be used in functions like [`then`] to ergonomically sequence a chain of
13/// [`Reactor`]s.
14///
15/// [`Reactor`]: crate::experimental::event::Reactor
16/// [`then`]: crate::experimental::event::then
17/// [`ThenChain`]: crate::experimental::event::ThenChain
18pub trait IntoReactor<T, S = ()> {
19    type Reactor: Reactor<T, S>;
20
21    fn into_reactor(self) -> Self::Reactor;
22}
23
24/// A type that reacts to [timed][`Timed`] [`Event`]s.
25///
26/// A reactor is a function that responds to [system][`SystemEvent`] and [data][`DataEvent`]
27/// events. Reactors are formed from combinators, which compose behaviors.
28///
29/// [`DataEvent`]: crate::experimental::event::DataEvent
30/// [`Event`]: crate::experimental::event::Event
31/// [`SystemEvent`]: crate::experimental::event::SystemEvent
32/// [`Timed`]: crate::experimental::clock::Timed
33pub trait Reactor<T, S = ()> {
34    /// The output type of successful responses from the reactor.
35    type Response;
36    /// The error type of failed responses from the reactor.
37    type Error;
38
39    /// Reacts to a [timed][`Timed`] [`Event`].
40    ///
41    /// # Errors
42    ///
43    /// Returns an [`Error`] if the reaction fails or the reactor cannot otherwise respond to the
44    /// event. Errors conditions are defined by implementations.
45    ///
46    /// [`Event`]: crate::experimental::event::Event
47    /// [`Timed`]: crate::experimental::clock::Timed
48    fn react(
49        &mut self,
50        event: Timed<Event<T>>,
51        context: Context<'_, S>,
52    ) -> Result<Self::Response, Self::Error>;
53
54    fn map_response<P, F>(self, f: F) -> MapResponse<Self, F>
55    where
56        Self: Sized,
57        F: FnMut(Self::Response) -> P,
58    {
59        MapResponse { reactor: self, f }
60    }
61
62    fn map_error<E, F>(self, f: F) -> MapError<Self, F>
63    where
64        Self: Sized,
65        F: FnMut(Self::Error) -> E,
66    {
67        MapError { reactor: self, f }
68    }
69
70    /// Reacts with this reactor and then responds with the given `response`, regardless of this
71    /// reactor's output.
72    fn respond<P>(self, response: P) -> Respond<Self, P>
73    where
74        Self: Sized,
75        P: Clone,
76    {
77        Respond { reactor: self, response }
78    }
79
80    /// Reacts with this reactor and then fails with the given `error`, regardless of this
81    /// reactor's output.
82    fn fail<E>(self, error: E) -> Fail<Self, E>
83    where
84        Self: Sized,
85        E: Clone,
86    {
87        Fail { reactor: self, error }
88    }
89
90    /// Reacts with this reactor and then the given reactor (regardless of outputs).
91    ///
92    /// The constructed reactor returns the output of the given (subsequent) reactor. See also the
93    /// [`event::then`] function.
94    ///
95    /// [`event::then`]: crate::experimental::event::then
96    fn then<R>(self, reactor: R) -> Then<Self, R>
97    where
98        Self: Sized,
99        T: Clone,
100        R: Reactor<T, S>,
101    {
102        Then { reactor: self, then: reactor }
103    }
104
105    /// Reacts with this reactor and then the given reactor if and only if this reactor returns
106    /// `Ok`.
107    ///
108    /// The constructed reactor returns either an error from this reactor or the output of the
109    /// given (subsequent) reactor. See also the [`event::and`] function.
110    ///
111    /// [`event::and`]: crate::experimental::event::and
112    fn and<R>(self, reactor: R) -> And<Self, R>
113    where
114        Self: Sized,
115        Self::Error: From<R::Error>,
116        T: Clone,
117        R: Reactor<T, S>,
118    {
119        And { reactor: self, and: reactor }
120    }
121
122    /// Reacts with this reactor and then the given reactor if and only if this reactor returns
123    /// `Err`.
124    ///
125    /// The constructed reactor returns either a response from this reactor or the output of the
126    /// given (subsequent) reactor. See also the [`event::or`] function.
127    ///
128    /// [`event::or`]: crate::experimental::event::or
129    fn or<R>(self, reactor: R) -> Or<Self, R>
130    where
131        Self: Sized,
132        T: Clone,
133        R: Reactor<T, S, Response = Self::Response>,
134    {
135        Or { reactor: self, or: reactor }
136    }
137
138    /// Constructs a `Reactor` that inspects the event and output of `self` with the given
139    /// function.
140    fn inspect<F>(self, f: F) -> impl Reactor<T, S, Response = Self::Response, Error = Self::Error>
141    where
142        Self: Sized,
143        T: Clone,
144        F: FnMut(&Timed<Event<T>>, &Result<Self::Response, Self::Error>),
145    {
146        Inspect { reactor: self, f }
147    }
148}
149
150impl<T, S, R, E, F> Reactor<T, S> for F
151where
152    F: FnMut(Timed<Event<T>>, Context<'_, S>) -> Result<R, E>,
153{
154    type Response = R;
155    type Error = E;
156
157    fn react(
158        &mut self,
159        event: Timed<Event<T>>,
160        context: Context<'_, S>,
161    ) -> Result<Self::Response, Self::Error> {
162        (self)(event, context)
163    }
164}
165
166#[derive(Debug)]
167pub struct Context<'s, S = ()> {
168    pub state: &'s mut S,
169}
170
171impl<'s, S> Context<'s, S> {
172    pub fn from_state(state: &'s mut S) -> Self {
173        Context { state }
174    }
175
176    pub fn with_state<'q, U>(self, state: &'q mut U) -> Context<'q, U> {
177        Context { state }
178    }
179
180    // Note too that this function must copy or clone any non-reference fields.
181    /// Reborrows the interior of the `Context`.
182    ///
183    /// This function constructs a `Context` from this one by reborrowing its reference fields. In
184    /// particular, this reborrows `state` and provides an ergonomic way to forward a `Context`
185    /// from one `Reactor` to another. It is **not** the `Context` that is borrowed in
186    /// `Reactor::react`, but the **fields** (`state`).
187    pub fn reborrow<'q>(&'q mut self) -> Context<'q, S>
188    where
189        's: 'q,
190    {
191        Context { state: self.state }
192    }
193}
194
195// This type merely forwards events to an inner `Reactor` with no additional behavior. It provides
196// an entrypoint for constructing `Reactor`s with the `on_data_record` function, which closes the
197// data record type `T`.
198#[derive(Clone, Copy, Debug)]
199#[repr(transparent)]
200pub struct OnDataRecord<R> {
201    reactor: R,
202}
203
204impl<T, S, R> Reactor<T, S> for OnDataRecord<R>
205where
206    R: Reactor<T, S>,
207{
208    type Response = R::Response;
209    type Error = R::Error;
210
211    #[inline(always)]
212    fn react(
213        &mut self,
214        event: Timed<Event<T>>,
215        context: Context<'_, S>,
216    ) -> Result<Self::Response, Self::Error> {
217        self.reactor.react(event, context)
218    }
219}
220
221#[derive(Clone, Copy, Debug)]
222pub struct MapResponse<R, F> {
223    reactor: R,
224    f: F,
225}
226
227impl<T, S, R, O, F> Reactor<T, S> for MapResponse<R, F>
228where
229    R: Reactor<T, S>,
230    F: FnMut(R::Response) -> O,
231{
232    type Response = O;
233    type Error = R::Error;
234
235    fn react(
236        &mut self,
237        event: Timed<Event<T>>,
238        context: Context<'_, S>,
239    ) -> Result<Self::Response, Self::Error> {
240        self.reactor.react(event, context).map(|response| (self.f)(response))
241    }
242}
243
244#[derive(Clone, Copy, Debug)]
245pub struct MapError<R, F> {
246    reactor: R,
247    f: F,
248}
249
250impl<T, S, R, O, F> Reactor<T, S> for MapError<R, F>
251where
252    R: Reactor<T, S>,
253    F: FnMut(R::Error) -> O,
254{
255    type Response = R::Response;
256    type Error = O;
257
258    fn react(
259        &mut self,
260        event: Timed<Event<T>>,
261        context: Context<'_, S>,
262    ) -> Result<Self::Response, Self::Error> {
263        self.reactor.react(event, context).map_err(|error| (self.f)(error))
264    }
265}
266
267#[derive(Clone, Copy, Debug)]
268pub struct MapDataRecord<R, F> {
269    reactor: R,
270    f: F,
271}
272
273impl<U, S, R, O, F> Reactor<U, S> for MapDataRecord<R, F>
274where
275    R: Reactor<O, S>,
276    F: FnMut(U, Context<'_, S>) -> O,
277{
278    type Response = R::Response;
279    type Error = R::Error;
280
281    fn react(
282        &mut self,
283        event: Timed<Event<U>>,
284        mut context: Context<'_, S>,
285    ) -> Result<Self::Response, Self::Error> {
286        let event = event.map_data_record(|record| (self.f)(record, context.reborrow()));
287        self.reactor.react(event, context)
288    }
289}
290
291#[derive(Clone, Copy, Debug)]
292pub struct FilterMapDataRecord<R, F> {
293    reactor: R,
294    f: F,
295}
296
297impl<U, S, R, O, F> Reactor<U, S> for FilterMapDataRecord<R, F>
298where
299    R: Reactor<O, S>,
300    F: FnMut(U, Context<'_, S>) -> Option<O>,
301{
302    type Response = Option<R::Response>;
303    type Error = R::Error;
304
305    fn react(
306        &mut self,
307        event: Timed<Event<U>>,
308        mut context: Context<'_, S>,
309    ) -> Result<Self::Response, Self::Error> {
310        event
311            .filter_map_data_record(|record| (self.f)(record, context.reborrow()))
312            .map(|event| self.reactor.react(event, context.reborrow()))
313            .transpose()
314    }
315}
316
317#[derive(Clone, Copy, Debug)]
318pub struct WithState<R, S> {
319    reactor: R,
320    state: S,
321}
322
323impl<T, S, U, R> Reactor<T, U> for WithState<R, S>
324where
325    R: Reactor<T, S>,
326{
327    type Response = R::Response;
328    type Error = R::Error;
329
330    fn react(
331        &mut self,
332        event: Timed<Event<T>>,
333        context: Context<'_, U>,
334    ) -> Result<Self::Response, Self::Error> {
335        self.reactor.react(event, context.with_state(&mut self.state))
336    }
337}
338
339#[derive(Clone, Copy, Debug)]
340pub struct MapState<R, F> {
341    reactor: R,
342    f: F,
343}
344
345impl<T, S, U, R, F> Reactor<T, S> for MapState<R, F>
346where
347    R: Reactor<T, U>,
348    F: FnMut(&mut S) -> U,
349{
350    type Response = R::Response;
351    type Error = R::Error;
352
353    fn react(
354        &mut self,
355        event: Timed<Event<T>>,
356        context: Context<'_, S>,
357    ) -> Result<Self::Response, Self::Error> {
358        let mut state = (self.f)(context.state);
359        self.reactor.react(event, context.with_state(&mut state))
360    }
361}
362
363#[derive(Clone, Copy, Debug)]
364pub struct Respond<R, P> {
365    reactor: R,
366    response: P,
367}
368
369impl<T, S, P, R> Reactor<T, S> for Respond<R, P>
370where
371    P: Clone,
372    R: Reactor<T, S>,
373{
374    type Response = P;
375    type Error = R::Error;
376
377    fn react(
378        &mut self,
379        event: Timed<Event<T>>,
380        context: Context<'_, S>,
381    ) -> Result<Self::Response, Self::Error> {
382        let _ = self.reactor.react(event, context);
383        Ok(self.response.clone())
384    }
385}
386
387#[derive(Clone, Copy, Debug)]
388pub struct Fail<R, E> {
389    reactor: R,
390    error: E,
391}
392
393impl<T, S, E, R> Reactor<T, S> for Fail<R, E>
394where
395    E: Clone,
396    R: Reactor<T, S>,
397{
398    type Response = R::Response;
399    type Error = E;
400
401    fn react(
402        &mut self,
403        event: Timed<Event<T>>,
404        context: Context<'_, S>,
405    ) -> Result<Self::Response, Self::Error> {
406        let _ = self.reactor.react(event, context);
407        Err(self.error.clone())
408    }
409}
410
411#[derive(Clone, Copy, Debug)]
412pub struct Then<R1, R2> {
413    reactor: R1,
414    then: R2,
415}
416
417impl<T, S, R1, R2> Reactor<T, S> for Then<R1, R2>
418where
419    T: Clone,
420    R1: Reactor<T, S>,
421    R2: Reactor<T, S>,
422{
423    type Response = R2::Response;
424    type Error = R2::Error;
425
426    fn react(
427        &mut self,
428        event: Timed<Event<T>>,
429        mut context: Context<'_, S>,
430    ) -> Result<Self::Response, Self::Error> {
431        let _ = self.reactor.react(event.clone(), context.reborrow());
432        self.then.react(event, context)
433    }
434}
435
436#[derive(Clone, Copy, Debug)]
437pub struct And<R1, R2> {
438    reactor: R1,
439    and: R2,
440}
441
442impl<T, S, R1, R2> Reactor<T, S> for And<R1, R2>
443where
444    T: Clone,
445    R1: Reactor<T, S>,
446    R1::Error: From<R2::Error>,
447    R2: Reactor<T, S>,
448{
449    type Response = R2::Response;
450    type Error = R1::Error;
451
452    fn react(
453        &mut self,
454        event: Timed<Event<T>>,
455        mut context: Context<'_, S>,
456    ) -> Result<Self::Response, Self::Error> {
457        self.reactor
458            .react(event.clone(), context.reborrow())
459            .and_then(|_| self.and.react(event, context.reborrow()).map_err(From::from))
460    }
461}
462
463#[derive(Clone, Copy, Debug)]
464pub struct Or<R1, R2> {
465    reactor: R1,
466    or: R2,
467}
468
469impl<T, S, R1, R2> Reactor<T, S> for Or<R1, R2>
470where
471    T: Clone,
472    R1: Reactor<T, S>,
473    R2: Reactor<T, S, Response = R1::Response>,
474{
475    type Response = R1::Response;
476    type Error = R2::Error;
477
478    fn react(
479        &mut self,
480        event: Timed<Event<T>>,
481        mut context: Context<'_, S>,
482    ) -> Result<Self::Response, Self::Error> {
483        match self.reactor.react(event.clone(), context.reborrow()) {
484            Ok(response) => Ok(response),
485            Err(_) => self.or.react(event, context.reborrow()),
486        }
487    }
488}
489
490#[derive(Clone, Copy, Debug)]
491pub struct Inspect<R, F> {
492    reactor: R,
493    f: F,
494}
495
496impl<T, S, R, F> Reactor<T, S> for Inspect<R, F>
497where
498    T: Clone,
499    R: Reactor<T, S>,
500    F: FnMut(&Timed<Event<T>>, &Result<R::Response, R::Error>),
501{
502    type Response = R::Response;
503    type Error = R::Error;
504
505    fn react(
506        &mut self,
507        event: Timed<Event<T>>,
508        mut context: Context<'_, S>,
509    ) -> Result<Self::Response, Self::Error> {
510        let output = self.reactor.react(event.clone(), context.reborrow());
511        (self.f)(&event, &output);
512        output
513    }
514}
515
516/// Container for dynamic collections in chain types.
517///
518/// This type is used in implementations of [`Reactor`] for chain types like [`ThenChain`] and
519/// provides a distinction with [`IntoReactor`] implementations. For example, `ThenChain<Vec<R>>`
520/// is **not** a reactor, but can be converted into `ThenChain<Dynamic<Vec<R>>>`, which is a
521/// reactor.
522///
523/// In this context, a dynamic collection is a collection of [`Reactor`]s constructed at runtime
524/// with an unknown length, namely [`Vec`]. For such collections, it is not possible to chain
525/// binary combinators like [`Then`], so a dynamic implementation is used instead like that for
526/// `ThenChain<Dynamic<Vec<R>>>`. Contrast this with static collections, like a tuple of
527/// [`Reactor`] types, for which the output reactor type is a chain of binary combinators like
528/// `Then<Then<A, B>, C>`.
529///
530/// [`IntoReactor`]: crate::experimental::event::IntoReactor
531/// [`Reactor`]: crate::experimental::event::Reactor
532/// [`Then`]: crate::experimental::event::Then
533/// [`ThenChain`]: crate::experimental::event::ThenChain
534/// [`Vec`]: std::vec::Vec
535#[derive(Clone, Copy, Debug)]
536#[repr(transparent)]
537pub struct Dynamic<R>(R);
538
539/// A type that can convert a collection of [`Reactor`]s into an ordered chain of [`Then`]
540/// combinators.
541///
542/// [`Reactor`]: crate::experimental::event::Reactor
543/// [`Then`]: crate::experimental::event::Then
544#[derive(Clone, Copy, Debug)]
545#[repr(transparent)]
546pub struct ThenChain<R>(R);
547
548impl<T, S, R> IntoReactor<T, S> for ThenChain<Vec<R>>
549where
550    T: Clone,
551    R: Reactor<T, S>,
552{
553    type Reactor = ThenChain<Dynamic<Vec<R>>>;
554
555    fn into_reactor(self) -> Self::Reactor {
556        ThenChain(Dynamic(self.0))
557    }
558}
559
560impl<T, S, R> Reactor<T, S> for ThenChain<Dynamic<Vec<R>>>
561where
562    T: Clone,
563    R: Reactor<T, S>,
564{
565    type Response = R::Response;
566    type Error = R::Error;
567
568    fn react(
569        &mut self,
570        event: Timed<Event<T>>,
571        mut context: Context<'_, S>,
572    ) -> Result<Self::Response, Self::Error> {
573        self.0
574             .0
575            .iter_mut()
576            .map(|reactor| reactor.react(event.clone(), context.reborrow()))
577            .next_back()
578            .expect("empty `then` combinator")
579    }
580}
581
582/// A type that can convert a collection of [`Reactor`]s into an ordered chain of [`And`]
583/// combinators.
584///
585/// [`And`]: crate::experimental::event::And
586/// [`Reactor`]: crate::experimental::event::Reactor
587#[derive(Clone, Copy, Debug)]
588#[repr(transparent)]
589pub struct AndChain<R>(R);
590
591impl<T, S, R> IntoReactor<T, S> for AndChain<Vec<R>>
592where
593    T: Clone,
594    R: Reactor<T, S>,
595{
596    type Reactor = AndChain<Dynamic<Vec<R>>>;
597
598    fn into_reactor(self) -> Self::Reactor {
599        AndChain(Dynamic(self.0))
600    }
601}
602
603impl<T, S, R> Reactor<T, S> for AndChain<Dynamic<Vec<R>>>
604where
605    T: Clone,
606    R: Reactor<T, S>,
607{
608    type Response = Vec<R::Response>;
609    type Error = R::Error;
610
611    fn react(
612        &mut self,
613        event: Timed<Event<T>>,
614        mut context: Context<'_, S>,
615    ) -> Result<Self::Response, Self::Error> {
616        self.0
617             .0
618            .iter_mut()
619            .map(|reactor| reactor.react(event.clone(), context.reborrow()))
620            .collect()
621    }
622}
623
624/// A type that can convert a collection of [`Reactor`]s into an ordered chain of [`Or`]
625/// combinators.
626///
627/// [`Or`]: crate::experimental::event::Ord
628/// [`Reactor`]: crate::experimental::event::Reactor
629#[derive(Clone, Copy, Debug)]
630#[repr(transparent)]
631pub struct OrChain<R>(R);
632
633impl<T, S, R> IntoReactor<T, S> for OrChain<Vec<R>>
634where
635    T: Clone,
636    R: Reactor<T, S>,
637{
638    type Reactor = OrChain<Dynamic<Vec<R>>>;
639
640    fn into_reactor(self) -> Self::Reactor {
641        OrChain(Dynamic(self.0))
642    }
643}
644
645impl<T, S, R> Reactor<T, S> for OrChain<Dynamic<Vec<R>>>
646where
647    T: Clone,
648    R: Reactor<T, S>,
649{
650    type Response = R::Response;
651    type Error = R::Error;
652
653    fn react(
654        &mut self,
655        event: Timed<Event<T>>,
656        mut context: Context<'_, S>,
657    ) -> Result<Self::Response, Self::Error> {
658        let mut outputs =
659            self.0 .0.iter_mut().map(|reactor| reactor.react(event.clone(), context.reborrow()));
660        let error = outputs.by_ref().take_while(Result::is_err).last();
661        outputs.next().or(error).expect("empty `or` combinator")
662    }
663}
664
665/// Constructs a [`Reactor`] that reacts to the [data record][`DataEvent::record`] `T`.
666///
667/// This function is typically paired with a sequencing combinator like [`then`] or [`and`] to
668/// construct a reactor for a particular type of data record.
669///
670/// [`and`]: crate::experimental::event::and
671/// [`DataEvent::record`]: crate::experimental::event::DataEvent::record
672/// [`Reactor`]: crate::experimental::event::Reactor
673/// [`then`]: crate::experimental::event::then
674pub fn on_data_record<T, R>(reactor: R) -> OnDataRecord<R>
675where
676    R: Reactor<T, ()>,
677{
678    OnDataRecord { reactor }
679}
680
681pub fn respond<T, S, P, R>(response: P, reactor: R) -> Respond<R, P>
682where
683    P: Clone,
684    R: Reactor<T, S>,
685{
686    reactor.respond(response)
687}
688
689pub fn fail<T, S, E, R>(error: E, reactor: R) -> Fail<R, E>
690where
691    E: Clone,
692    R: Reactor<T, S>,
693{
694    reactor.fail(error)
695}
696
697pub fn map_data_record<T, S, O, F, R>(f: F, reactor: R) -> MapDataRecord<R, F>
698where
699    F: FnMut(T, Context<'_, S>) -> O,
700    R: Reactor<O, S>,
701{
702    MapDataRecord { reactor, f }
703}
704
705pub fn filter_map_data_record<T, U, S, O, F, R>(f: F, reactor: R) -> FilterMapDataRecord<R, F>
706where
707    F: FnMut(T, Context<'_, S>) -> Option<O>,
708    R: Reactor<U, S>,
709{
710    FilterMapDataRecord { reactor, f }
711}
712
713pub fn with_state<T, S, R>(state: S, reactor: R) -> WithState<R, S>
714where
715    R: Reactor<T, S>,
716{
717    WithState { reactor, state }
718}
719
720pub fn map_state<T, S, O, F, R>(f: F, reactor: R) -> MapState<R, F>
721where
722    F: FnMut(&mut S) -> O,
723    R: Reactor<T, O>,
724{
725    MapState { reactor, f }
726}
727
728/// Reacts with the given reactors in order (regardless of outputs).
729///
730/// This function accepts a type `R` for which `ThenChain<R>` implements [`IntoReactor`].
731/// [`ThenChain`] implements this trait for collection types, most notably non-unary tuple types
732/// and [`Vec`] of [`Reactor`] types.
733///
734/// The constructed reactor returns the output of the last reactor. See also the [`Reactor::then`]
735/// function.
736///
737/// [`IntoReactor`]: crate::experimental::event::IntoReactor
738/// [`Reactor`]: crate::experimental::event::Reactor
739/// [`Reactor::then`]: crate::experimental::event::Reactor::then
740/// [`ThenChain`]: crate::experimental::event::ThenChain
741pub fn then<T, S, R>(reactors: R) -> <ThenChain<R> as IntoReactor<T, S>>::Reactor
742where
743    ThenChain<R>: IntoReactor<T, S>,
744    T: Clone,
745{
746    ThenChain(reactors).into_reactor()
747}
748
749/// Reacts with the given reactors in order until the first error.
750///
751/// This function accepts a type `R` for which `AndChain<R>` implements [`IntoReactor`].
752/// [`AndChain`] implements this trait for collection types, most notably non-unary tuple types and
753/// [`Vec`] of [`Reactor`] types.
754///
755/// The constructed reactor returns either the responses from the given reactors or the first
756/// encountered error. See also the [`Reactor::and`] function.
757///
758/// [`AndChain`]: crate::experimental::event::AndChain
759/// [`IntoReactor`]: crate::experimental::event::IntoReactor
760/// [`Reactor`]: crate::experimental::event::Reactor
761/// [`Reactor::and`]: crate::experimental::event::Reactor::and
762pub fn and<T, S, R>(reactors: R) -> <AndChain<R> as IntoReactor<T, S>>::Reactor
763where
764    AndChain<R>: IntoReactor<T, S>,
765    T: Clone,
766{
767    AndChain(reactors).into_reactor()
768}
769
770/// Reacts with the given reactors in order until the first response.
771///
772/// This function accepts a type `R` for which `OrChain<R>` implements [`IntoReactor`]. [`OrChain`]
773/// implements this trait for collection types, most notably non-unary tuple types and [`Vec`] of
774/// [`Reactor`] types.
775///
776/// The constructed reactor returns either the first response from the given reactors or the error
777/// from the last reactor. See also the [`Reactor::or`] function.
778///
779/// [`IntoReactor`]: crate::experimental::event::IntoReactor
780/// [`OrChain`]: crate::experimental::event::OrChain
781/// [`Reactor`]: crate::experimental::event::Reactor
782/// [`Reactor::or`]: crate::experimental::event::Reactor::or
783pub fn or<T, S, R>(reactors: R) -> <OrChain<R> as IntoReactor<T, S>>::Reactor
784where
785    OrChain<R>: IntoReactor<T, S>,
786    T: Clone,
787{
788    OrChain(reactors).into_reactor()
789}
790
791/// Invokes another macro with non-unary tuple subsequences.
792///
793/// This macro invokes another macro with the non-unary subsequences of a single tuple parameter
794/// (down to a binary tuple). That is, given a macro `f` and the starting tuple `(T1, T2, T3)`,
795/// this macro invokes `f!((T1, T2, T3))` and `f!((T2, T3))`. Note that in this example `f!((T3,))`
796/// is **not** invoked, as `(T3,)` is a unary tuple.
797macro_rules! with_nonunary_tuples {
798    ($f:ident, ( $head:ident, $tail:ident $(,)? ) $(,)?) => {
799        $f!(($head, $tail));
800    };
801    ($f:ident, ( $head:ident, $body:ident, $($tail:ident), +$(,)? ) $(,)?) => {
802        $f!(($head,$body,$($tail,)*));
803        with_nonunary_tuples!($f, ( $body,$($tail,)+ ));
804    };
805}
806
807/// Invokes another macro with the non-unary subsequences of supported combinator tuples.
808macro_rules! with_reactor_combinator_chain_tuples {
809    ($f:ident) => {
810        // This defines the set of tuples supported by chaining combinators.
811        with_nonunary_tuples!($f, (T1, T2, T3, T4, T5, T6, T7, T8));
812    };
813}
814
815/// Constructs the chained type name of a sequencing combinator for a **reversed** tuple of
816/// `Reactor` types.
817///
818/// See `forward_combinator_chain_tuple_output_type`.
819macro_rules! reverse_combinator_chain_tuple_output_type {
820    ($combinator:ident, ( $head:ident,$body:ident,$($tail:ident,)+ )$(,)?) => {
821        $combinator<reverse_combinator_chain_tuple_output_type!($combinator, ($body,$($tail,)+)), $head>
822    };
823    ($combinator:ident, ( $head:ident,$tail:ident$(,)? )$(,)?) => {
824        $combinator<$tail, $head>
825    };
826}
827
828/// Constructs the chained type name of a sequencing combinator for a tuple of `Reactor` types.
829///
830/// Given the sequencing combinator `Then` and a tuple of `Reactor` types `(C, B, A)`, this macro
831/// constructs the identifier `Then<Then<A, B>, C>`. This identifier names the `Reactor` type of
832/// the chained expression `A.then(B).then(C)`.
833macro_rules! forward_combinator_chain_tuple_output_type {
834    ($combinator:ident, ( $($forward:ident),*$(,)? )) => {
835        forward_combinator_chain_tuple_output_type!($combinator, ($($forward,)*); ())
836    };
837    ($combinator:ident, ( $head:ident,$($tail:ident),*$(,)? ); ( $($reverse:ident),*$(,)? )) => {
838        forward_combinator_chain_tuple_output_type!($combinator, ($($tail,)*); ($head,$($reverse,)*))
839    };
840    // This matcher is the base case: the tuple is reversed and so is forwarded to
841    // `reverse_combinator_chain_tuple_output_type`.
842    ($combinator:ident, ( $(,)? ); ( $($reverse:ident),*$(,)? )) => {
843        reverse_combinator_chain_tuple_output_type!($combinator, ( $($reverse,)* ))
844    };
845}
846
847/// Implements [`IntoReactor`] for [`ThenChain`] of tuple types.
848///
849/// [`IntoReactor`]: crate::experimental::event::IntoReactor
850/// [`ThenChain`]: crate::experimental::event::ThenChain
851macro_rules! impl_into_reactor_for_then_chain_tuple {
852    (( $head:ident, $($tail:ident $(,)?)+ )) => {
853        impl<T, S, $head $(,$tail)+> IntoReactor<T, S> for ThenChain<($head $(,$tail)+)>
854        where
855            T: Clone,
856            $head: Reactor<T, S>,
857            $(
858                $tail: Reactor<T, S, Response = $head::Response>,
859                $head::Error: From<$tail::Error>,
860            )+
861        {
862            type Reactor = forward_combinator_chain_tuple_output_type!(Then, ($head $(,$tail)+));
863
864            #[allow(non_snake_case)]
865            #[allow(unused_assignments)]
866            fn into_reactor(self) -> Self::Reactor {
867                let ($head $(, $tail)+) = self.0;
868                $head
869                $(
870                    .then($tail)
871                )+
872            }
873        }
874    }
875}
876with_reactor_combinator_chain_tuples!(impl_into_reactor_for_then_chain_tuple);
877
878/// Implements [`IntoReactor`] for [`AndChain`] of tuple types.
879///
880/// [`AndChain`]: crate::experimental::event::AndChain
881/// [`IntoReactor`]: crate::experimental::event::IntoReactor
882macro_rules! impl_into_reactor_for_and_chain_tuple {
883    (( $head:ident, $($tail:ident $(,)?)+ )) => {
884        impl<T, S, $head $(,$tail)+> IntoReactor<T, S> for AndChain<($head $(,$tail)+)>
885        where
886            T: Clone,
887            $head: Reactor<T, S>,
888            $(
889                $tail: Reactor<T, S>,
890                $head::Error: From<$tail::Error>,
891            )+
892        {
893            type Reactor = forward_combinator_chain_tuple_output_type!(And, ($head $(,$tail)+));
894
895            #[allow(non_snake_case)]
896            #[allow(unused_assignments)]
897            fn into_reactor(self) -> Self::Reactor {
898                let ($head $(, $tail)+) = self.0;
899                $head
900                $(
901                    .and($tail)
902                )+
903            }
904        }
905    }
906}
907with_reactor_combinator_chain_tuples!(impl_into_reactor_for_and_chain_tuple);
908
909/// Implements [`IntoReactor`] for [`OrChain`] of tuple types.
910///
911/// [`IntoReactor`]: crate::experimental::event::IntoReactor
912/// [`OrChain`]: crate::experimental::event::OrChain
913macro_rules! impl_into_reactor_for_or_chain_tuple {
914    (( $head:ident, $($tail:ident $(,)?)+ )) => {
915        impl<T, S, $head $(,$tail)+> IntoReactor<T, S> for OrChain<($head $(,$tail)+)>
916        where
917            T: Clone,
918            $head: Reactor<T, S>,
919            $(
920                $tail: Reactor<T, S, Response = $head::Response>,
921                $head::Error: From<$tail::Error>,
922            )+
923        {
924            type Reactor = forward_combinator_chain_tuple_output_type!(Or, ($head $(,$tail)+));
925
926            #[allow(non_snake_case)]
927            #[allow(unused_assignments)]
928            fn into_reactor(self) -> Self::Reactor {
929                let ($head $(, $tail)+) = self.0;
930                $head
931                $(
932                    .or($tail)
933                )+
934            }
935        }
936    }
937}
938with_reactor_combinator_chain_tuples!(impl_into_reactor_for_or_chain_tuple);