roopes_core/patterns/transformer_chain/
heap.rs

1//!
2#![cfg_attr(feature = "doc-images",
3  cfg_attr(
4    all(),
5    doc = ::embed_doc_image::embed_image!(
6        "transformer-chain-diagram",
7        "src/patterns/transformer_chain/transformer_chain.svg"
8)))]
9//! Provides a heap-based [`Head`] which redirects
10//! [`Transformer::transform`] calls to a delegate
11//! [`Transformer`], then enables additional
12//! stages to be added arbitrarily.
13//!
14//! ![transformer chain diagram][transformer-chain-diagram]
15
16use crate::primitives::transformer::{
17    self,
18    Transformer,
19};
20use delegate::delegate;
21
22/// The first stage in the [`Transformer`] Chain.
23/// Unique because it does not an
24/// the prior [`Transformer`], but is instead
25/// given input from the client.
26pub struct Head<I, O>
27{
28    transformer: Box<dyn Transformer<I, O>>,
29}
30
31impl<I, O> Head<I, O>
32{
33    /// Creates a new [`Head`] with a given
34    /// [`Box`]ed [`Transformer`].
35    #[must_use]
36    pub fn new(transformer: Box<dyn Transformer<I, O>>) -> Head<I, O>
37    {
38        Head { transformer }
39    }
40
41    /// Adds a stage of execution, giving a new
42    /// [`Heap`] back.
43    pub fn push<N, T>(
44        self,
45        transformer: T,
46    ) -> Heap<I, N, O>
47    where
48        T: Transformer<O, N> + 'static,
49        N: 'static,
50        O: 'static,
51        I: 'static,
52    {
53        let prev = Box::new(self);
54        let transformer = Box::new(transformer);
55
56        Heap { prev, transformer }
57    }
58}
59
60#[allow(clippy::inline_always)]
61impl<I, O> Transformer<I, O> for Head<I, O>
62{
63    delegate! {
64            to self.transformer {
65            fn transform(
66                &self,
67                input: &I,
68            ) -> O;
69        }
70    }
71}
72
73/// Stores previous transformations, and the
74/// ability to produce new transformations.
75pub struct Heap<I, O, P>
76{
77    prev: Box<dyn Transformer<I, P>>,
78    transformer: Box<dyn Transformer<P, O>>,
79}
80
81impl<I, O, P> Heap<I, O, P>
82{
83    /// Adds a stage of execution, giving a new
84    /// [`Heap`] back.
85    #[must_use]
86    pub fn push<N, E>(
87        self,
88        transformer: E,
89    ) -> Heap<I, N, O>
90    where
91        E: Transformer<O, N> + 'static,
92        O: 'static,
93        N: 'static,
94        I: 'static,
95        P: 'static,
96    {
97        let prev = Box::new(self);
98        let transformer = Box::new(transformer);
99
100        Heap { prev, transformer }
101    }
102}
103
104impl<I, O, P> Transformer<I, O> for Heap<I, O, P>
105{
106    #[must_use]
107    fn transform(
108        &self,
109        input: &I,
110    ) -> O
111    {
112        self.transformer.transform(&self.prev.transform(input))
113    }
114}