Skip to main content

tabnas_render/
renderers.rs

1//! This crate's implementation of alchemy's `Renderers`: the interface a
2//! compiled alchemy program makes its rendering stages through.
3//!
4//! alchemy's runtime writes a program's output through a [`JsonRenderer`],
5//! a [`CsvRenderer`], [`RecordsToJson`], a [`Join`], a [`ReplaceText`] and
6//! a [`WriteOut`], and constructs none of them: the host passes
7//! [`renderers()`] to `tabnas_alchemy::compile`, and each stage is made
8//! through it, exactly as the constructor named would make it.
9
10use std::io::Write;
11use std::sync::Arc;
12
13use tabnas_alchemy::shared::{
14    CsvOptions, Fail, JoinOut, JsonOptions, Limits, Metrics, Renderers, Sink, TableSink, TextOut,
15};
16
17use crate::csv::CsvRenderer;
18use crate::json::JsonRenderer;
19use crate::records::RecordsToJson;
20use crate::text::{Join, ReplaceText, WriteOut};
21
22/// The renderers this crate implements, for alchemy's `Renderers`: every
23/// method is the constructor of the same name.
24#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
25pub struct RenderRenderers;
26
27/// This crate's renderers, to pass to `tabnas_alchemy::compile`.
28pub fn renderers() -> RenderRenderers {
29    RenderRenderers
30}
31
32impl Renderers for RenderRenderers {
33    fn json(&self, out: Box<dyn TextOut + Send>, options: JsonOptions) -> Box<dyn Sink + Send> {
34        Box::new(JsonRenderer::new(out, options))
35    }
36
37    fn csv(
38        &self,
39        out: Box<dyn TextOut + Send>,
40        options: CsvOptions,
41    ) -> Result<Box<dyn TableSink + Send>, Fail> {
42        Ok(Box::new(CsvRenderer::new(out, options)?))
43    }
44
45    fn records_to_json(&self, sink: Box<dyn Sink + Send>) -> Box<dyn TableSink + Send> {
46        Box::new(RecordsToJson::new(sink))
47    }
48
49    fn join<'a>(
50        &self,
51        out: Box<dyn TextOut + Send + 'a>,
52        separator: &str,
53    ) -> Box<dyn JoinOut + Send + 'a> {
54        Box::new(Join::new(out, separator))
55    }
56
57    fn replace_text<'a>(
58        &self,
59        out: Box<dyn TextOut + Send + 'a>,
60        from: &str,
61        to: &str,
62    ) -> Box<dyn TextOut + Send + 'a> {
63        Box::new(ReplaceText::new(out, from, to))
64    }
65
66    fn write_out(
67        &self,
68        writer: Box<dyn Write + Send>,
69        limits: &Limits,
70        metrics: Arc<Metrics>,
71    ) -> Box<dyn TextOut + Send> {
72        Box::new(
73            WriteOut::new(writer)
74                .with_limits(limits)
75                .with_metrics(metrics),
76        )
77    }
78}