redact_composer_core/render/
mod.rs

1/// Context structs involved during composition rendering.
2pub mod context;
3
4/// Basic n-ary tree implementation.
5pub mod tree;
6
7use crate::error::RendererError;
8
9use std::fmt::Formatter;
10use std::iter::successors;
11use std::ops::Deref;
12use std::{any::TypeId, collections::HashMap, fmt::Debug, ops::Add};
13use Vec;
14
15use crate::{Element, Segment, SegmentRef};
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Serialize};
19
20use crate::render::context::CompositionContext;
21
22/// [`Result`](std::result::Result) with a default error type of [`RendererError`].
23pub type Result<T, E = RendererError> = std::result::Result<T, E>;
24
25/// Defines render behavior for a specific [`Element`](Self::Element).
26///
27/// Every render operation during composition receives a
28/// [`SegmentRef<Self::Element>`](crate::SegmentRef<Self::Element>) with
29/// [`CompositionContext`] and may return [`Vec<Segment`>] on success, or
30/// [`RendererError::MissingContext`] in the case that its render dependencies are not satisfied
31/// (which will be retried later).
32pub trait Renderer {
33    /// The particular [`Element`] this [`Renderer`] renders.
34    type Element: Element;
35
36    /// Renderers a [`SegmentRef<Self::Element>`] with [`CompositionContext`], returning additional
37    /// [`Segment`]s as children.
38    fn render(
39        &self,
40        segment: SegmentRef<Self::Element>,
41        context: CompositionContext,
42    ) -> Result<Vec<Segment>>;
43}
44
45/// Wraps a [`Segment`] with additional render-related information.
46#[derive(Debug)]
47#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
48pub struct RenderSegment {
49    /// The wrapped [`Segment`].
50    #[cfg_attr(feature = "serde", serde(flatten))]
51    pub segment: Segment,
52    /// Seed used for [`CompositionContext`] rng when this segment is rendered.
53    pub seed: u64,
54    /// Initially `false`, becoming `true` only after this segment has been successfully rendered.
55    pub rendered: bool,
56    /// Stores the latest encountered [`RendererError`] for debugging.
57    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
58    pub error: Option<RendererError>,
59}
60
61/// Implements a [`Renderer`] via a wrapped closure.
62///
63/// Most commonly used to implement a [`Renderer`] which does not require its own struct/state.
64///
65/// ```
66/// # use serde::{Deserialize, Serialize};
67/// # use redact_composer_core::derive::Element;
68/// # use redact_composer_core::elements::PlayNote;
69/// # use redact_composer_core::IntoSegment;
70/// # use redact_composer_core::render::AdhocRenderer;
71/// # #[derive(Element, Debug, Serialize, Deserialize)]
72/// # struct SomeElement;
73/// let renderer = AdhocRenderer::<SomeElement>::new(|segment, context| {
74///     Ok(vec![
75///         PlayNote {note: 60, velocity: 100 }
76///         .over(segment.timing)
77///     ])
78/// });
79/// ```
80#[allow(missing_debug_implementations)] // TODO
81pub struct AdhocRenderer<T: Element> {
82    /// Closure implementing the signature of
83    /// [`Renderer::render`](crate::render::Renderer::render).
84    #[allow(clippy::type_complexity)]
85    func: Box<dyn Fn(SegmentRef<T>, CompositionContext) -> Result<Vec<Segment>>>,
86}
87
88impl<T: Element> AdhocRenderer<T> {
89    /// Creates an [`AdhocRenderer`] from a closure.
90    pub fn new(
91        func: impl Fn(SegmentRef<T>, CompositionContext) -> Result<Vec<Segment>> + 'static,
92    ) -> AdhocRenderer<T> {
93        AdhocRenderer {
94            func: Box::new(func),
95        }
96    }
97}
98
99impl<T: Element> Renderer for AdhocRenderer<T> {
100    type Element = T;
101
102    /// Renders a [`Element`] by calling the [`AdhocRenderer`]s wrapped closure.
103    fn render(
104        &self,
105        segment: SegmentRef<Self::Element>,
106        context: CompositionContext,
107    ) -> Result<Vec<Segment>> {
108        (self.func)(segment, context)
109    }
110}
111
112/// A group of [`Renderer`]s for a single [`Renderer::Element`]. This group is itself a
113/// [`Renderer`] which renders as a unit, returning [`crate::error::RendererError`] if any of its
114/// [`Renderer`]s do.
115#[allow(missing_debug_implementations)] // TODO
116pub struct RendererGroup<T> {
117    /// The renderers of this group.
118    pub renderers: Vec<Box<dyn Renderer<Element = T>>>,
119}
120
121impl<T> RendererGroup<T> {
122    /// Creates an empty [`RendererGroup`].
123    pub fn new() -> RendererGroup<T> {
124        RendererGroup { renderers: vec![] }
125    }
126}
127
128impl<T> Default for RendererGroup<T> {
129    fn default() -> Self {
130        RendererGroup::new()
131    }
132}
133
134impl<T, R> Add<R> for RendererGroup<T>
135where
136    R: Renderer<Element = T> + 'static,
137{
138    type Output = Self;
139
140    fn add(mut self, rhs: R) -> Self::Output {
141        self.renderers.push(Box::new(rhs));
142
143        self
144    }
145}
146
147impl<T: Element> Renderer for RendererGroup<T> {
148    type Element = T;
149
150    fn render(
151        &self,
152        segment: SegmentRef<Self::Element>,
153        context: CompositionContext,
154    ) -> Result<Vec<Segment>> {
155        let mut result_children = vec![];
156
157        for renderer in &self.renderers {
158            result_children.append(&mut renderer.render(segment, context)?);
159        }
160
161        Ok(result_children)
162    }
163}
164
165trait ErasedRenderer {
166    fn render(&self, segment: &Segment, context: CompositionContext) -> Result<Vec<Segment>>;
167}
168
169impl<T: Renderer> ErasedRenderer for T {
170    fn render(&self, segment: &Segment, context: CompositionContext) -> Result<Vec<Segment>> {
171        self.render(segment.try_into()?, context)
172    }
173}
174
175/// A mapping of [`Element`] to [`Renderer`]s used to delegate rendering of generic
176/// [`Segment`]s via their [`Element`]. Only one [`Renderer`] per type is
177/// allowed in the current implementation.
178#[allow(missing_debug_implementations)] // TODO
179#[derive(Default)]
180pub struct RenderEngine {
181    renderers: HashMap<TypeId, Box<dyn ErasedRenderer>>,
182}
183
184impl Debug for RenderEngine {
185    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
186        // TODO
187        write!(f, "RenderEngine {{ /* TODO */ }}")
188    }
189}
190
191impl RenderEngine {
192    /// Creates an empty [`RenderEngine`].
193    pub fn new() -> RenderEngine {
194        RenderEngine {
195            renderers: HashMap::new(),
196        }
197    }
198
199    /// Adds a [`Renderer`] to this [`RenderEngine`], replacing any existing [`Renderer`] for
200    /// the corresponding [`Renderer::Element`].
201    pub fn add_renderer<R: Renderer + 'static>(&mut self, renderer: R) {
202        self.renderers
203            .insert(TypeId::of::<R::Element>(), Box::new(renderer));
204    }
205
206    /// Returns the [`Renderer`] corresponding to the given [`&dyn Element`], if one exists.
207    fn renderer_for(&self, element: &dyn Element) -> Option<&dyn ErasedRenderer> {
208        self.renderers
209            .get(&element.as_any().type_id())
210            .map(Box::deref)
211    }
212
213    /// Determines if this [`RenderEngine`] can render a given `&dyn` [`Element`]. (i.e. whether
214    /// it has a mapped renderer for the given `&dyn` [`Element`])
215    ///
216    /// This checks not only the given `&dyn` [`Element`], but also any types it wraps.
217    pub fn can_render(&self, element: &dyn Element) -> bool {
218        successors(Some(element), |&s| s.wrapped_element()).any(|s| self.can_render_specific(s))
219    }
220
221    /// Determines if this [`RenderEngine`] can render a given `&dyn` [`Element`]. Only checks
222    /// the given type, ignoring any wrapped types (unlike [`Self::can_render`]).
223    pub fn can_render_specific(&self, element: &dyn Element) -> bool {
224        self.renderers.contains_key(&element.as_any().type_id())
225    }
226
227    /// Renders a [`Element`] over a given time range with supplied context, delegating to
228    /// [`Renderer`]s mapped to its type and wrapped types if any. If no mapped [`Renderer`]
229    /// for the type or wrapped types exists, [`None`] is returned.
230    pub fn render(
231        &self,
232        segment: &Segment,
233        context: CompositionContext,
234    ) -> Option<Result<Vec<Segment>>> {
235        let renderables = successors(Some(&*segment.element), |&s| s.wrapped_element())
236            .filter(|s| self.can_render_specific(*s))
237            .collect::<Vec<_>>();
238
239        if renderables.is_empty() {
240            None
241        } else {
242            let mut generated_segments = vec![];
243
244            for renderable in renderables {
245                if let Some(renderer) = self.renderer_for(renderable) {
246                    let result = renderer.render(segment, context);
247
248                    if let Ok(mut segments) = result {
249                        generated_segments.append(&mut segments);
250                    } else {
251                        return Some(result);
252                    }
253                }
254            }
255
256            Some(Ok(generated_segments))
257        }
258    }
259}
260
261impl<R, S> Add<R> for RenderEngine
262where
263    R: Renderer<Element = S> + 'static,
264    S: Element,
265{
266    type Output = Self;
267
268    fn add(mut self, rhs: R) -> Self::Output {
269        self.add_renderer(rhs);
270
271        self
272    }
273}
274
275impl Add<RenderEngine> for RenderEngine {
276    type Output = Self;
277
278    fn add(mut self, rhs: RenderEngine) -> Self::Output {
279        self.renderers.extend(rhs.renderers);
280
281        self
282    }
283}