Skip to main content

sailfish/
lib.rs

1//! Sailfish is a simple, small, and extremely fast template engine for Rust.
2//! Before reading this reference,
3//! I recommend reading [User guide](https://rust-sailfish.github.io/sailfish/).
4//!
5//! This crate contains utilities for rendering sailfish template.
6//! If you want to use sailfish templates, import `sailfish-macros` crate and use
7//! derive macro `#[derive(TemplateOnce)]`, `#[derive(TemplateMut)]` or `#[derive(Template)]`.
8//!
9//! In most cases you don't need to care about the `runtime` module in this crate, but
10//! if you want to render custom data inside templates, you must implement
11//! `runtime::Render` trait for that type.
12//!
13//! ```compile_fail
14//! #[allow(rustdoc::invalid_rust_codeblocks)]
15//! use sailfish::Template;
16//!
17//! #[derive(Template)]
18//! #[template(path = "hello.stpl")]
19//! struct HelloTemplate {
20//!     messages: Vec<String>
21//! }
22//!
23//! fn main() {
24//!     let ctx = HelloTemplate {
25//!         messages: vec!["foo".to_string(), "bar".to_string()]
26//!     };
27//!
28//!     println!("{}", ctx.render().unwrap());
29//! }
30//! ```
31
32#![doc(
33    html_logo_url = "https://raw.githubusercontent.com/rust-sailfish/sailfish/master/resources/icon.png"
34)]
35#![cfg_attr(docsrs, feature(doc_cfg))]
36#![allow(clippy::redundant_closure)]
37#![deny(missing_docs)]
38
39pub mod runtime;
40
41use runtime::Buffer;
42pub use runtime::{RenderError, RenderResult};
43#[cfg(feature = "derive")]
44#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
45pub use sailfish_macros::{Template, TemplateMut, TemplateOnce, TemplateSimple};
46
47/// Template which can be accessed without using `self`.
48pub trait TemplateSimple: Sized {
49    /// Render the template and return the rendering result as `RenderResult`
50    ///
51    /// This method never returns `Err`, unless you explicitly return RenderError
52    /// inside templates
53    ///
54    /// When you use `render_once` method, total rendered size will be cached, and at
55    /// the next time, buffer will be pre-allocated based on the cached length.
56    ///
57    /// If you don't want this behaviour, you can use `render_once_to` method instead.
58    fn render_once(self) -> runtime::RenderResult;
59
60    /// Render the template and append the result to `buf`.
61    ///
62    /// This method never returns `Err`, unless you explicitly return RenderError
63    /// inside templates
64    ///
65    /// ```
66    /// use sailfish::TemplateSimple;
67    /// use sailfish::runtime::Buffer;
68    ///
69    /// # pub struct HelloTemplate {
70    /// #   messages: Vec<String>,
71    /// # }
72    /// #
73    /// # impl TemplateSimple for HelloTemplate {
74    /// #     fn render_once(self) -> Result<String, sailfish::RenderError> {
75    /// #         Ok(String::new())
76    /// #     }
77    /// #
78    /// #     fn render_once_to(self, buf: &mut Buffer)
79    /// #             -> Result<(), sailfish::RenderError> {
80    /// #         Ok(())
81    /// #     }
82    /// # }
83    /// #
84    /// let tpl = HelloTemplate {
85    ///     messages: vec!["foo".to_string()]
86    /// };
87    ///
88    /// // custom pre-allocation
89    /// let mut buffer = Buffer::with_capacity(100);
90    /// tpl.render_once_to(&mut buffer).unwrap();
91    /// ```
92    fn render_once_to(self, buf: &mut Buffer) -> Result<(), RenderError>;
93}
94
95/// Template that can be rendered with consuming itself.
96pub trait TemplateOnce: Sized {
97    /// Render the template and return the rendering result as `RenderResult`
98    ///
99    /// This method never returns `Err`, unless you explicitly return RenderError
100    /// inside templates
101    ///
102    /// When you use `render_once` method, total rendered size will be cached, and at
103    /// the next time, buffer will be pre-allocated based on the cached length.
104    ///
105    /// If you don't want this behaviour, you can use `render_once_to` method instead.
106    fn render_once(self) -> runtime::RenderResult;
107
108    /// Render the template and append the result to `buf`.
109    ///
110    /// This method never returns `Err`, unless you explicitly return RenderError
111    /// inside templates
112    ///
113    /// ```
114    /// use sailfish::TemplateOnce;
115    /// use sailfish::runtime::Buffer;
116    ///
117    /// # pub struct HelloTemplate {
118    /// #   messages: Vec<String>,
119    /// # }
120    /// #
121    /// # impl TemplateOnce for HelloTemplate {
122    /// #     fn render_once(self) -> Result<String, sailfish::RenderError> {
123    /// #         Ok(String::new())
124    /// #     }
125    /// #
126    /// #     fn render_once_to(self, buf: &mut Buffer)
127    /// #             -> Result<(), sailfish::RenderError> {
128    /// #         Ok(())
129    /// #     }
130    /// # }
131    /// #
132    /// let tpl = HelloTemplate {
133    ///     messages: vec!["foo".to_string()]
134    /// };
135    ///
136    /// // custom pre-allocation
137    /// let mut buffer = Buffer::with_capacity(100);
138    /// tpl.render_once_to(&mut buffer).unwrap();
139    /// ```
140    fn render_once_to(self, buf: &mut Buffer) -> Result<(), RenderError>;
141}
142
143/// Template that is mutable and can be rendered any number of times.
144pub trait TemplateMut: TemplateOnce {
145    /// Render the template and return the rendering result as `RenderResult`
146    ///
147    /// This method never returns `Err`, unless you explicitly return RenderError
148    /// inside templates
149    ///
150    /// When you use `render` method, total rendered size will be cached, and at
151    /// the next time, buffer will be pre-allocated based on the cached length.
152    ///
153    /// If you don't want this behaviour, you can use `render_to` method instead.
154    fn render_mut(&mut self) -> runtime::RenderResult;
155
156    /// Render the template and append the result to `buf`.
157    ///
158    /// This method never returns `Err`, unless you explicitly return RenderError
159    /// inside templates
160    ///
161    /// ```
162    /// use sailfish::{TemplateOnce, TemplateMut};
163    /// use sailfish::runtime::Buffer;
164    ///
165    /// # pub struct HelloTemplate {
166    /// #   messages: Vec<String>,
167    /// # }
168    /// #
169    /// # impl TemplateOnce for HelloTemplate {
170    /// #     fn render_once(self) -> Result<String, sailfish::RenderError> {
171    /// #         Ok(String::new())
172    /// #     }
173    /// #
174    /// #     fn render_once_to(self, buf: &mut Buffer)
175    /// #             -> Result<(), sailfish::RenderError> {
176    /// #         Ok(())
177    /// #     }
178    /// # }
179    /// #
180    /// # impl TemplateMut for HelloTemplate {
181    /// #     fn render_mut(&mut self) -> Result<String, sailfish::RenderError> {
182    /// #         Ok(String::new())
183    /// #     }
184    /// #
185    /// #     fn render_mut_to(&mut self, buf: &mut Buffer)
186    /// #             -> Result<(), sailfish::RenderError> {
187    /// #         Ok(())
188    /// #     }
189    /// # }
190    /// #
191    /// let mut tpl = HelloTemplate {
192    ///     messages: vec!["foo".to_string()]
193    /// };
194    ///
195    /// // custom pre-allocation
196    /// let mut buffer = Buffer::with_capacity(100);
197    /// tpl.render_mut_to(&mut buffer).unwrap();
198    /// ```
199    fn render_mut_to(&mut self, buf: &mut Buffer) -> Result<(), RenderError>;
200}
201
202/// Template that can be rendered any number of times.
203pub trait Template: TemplateMut {
204    /// Render the template and return the rendering result as `RenderResult`
205    ///
206    /// This method never returns `Err`, unless you explicitly return RenderError
207    /// inside templates
208    ///
209    /// When you use `render` method, total rendered size will be cached, and at
210    /// the next time, buffer will be pre-allocated based on the cached length.
211    ///
212    /// If you don't want this behaviour, you can use `render_to` method instead.
213    fn render(&self) -> runtime::RenderResult;
214
215    /// Render the template and append the result to `buf`.
216    ///
217    /// This method never returns `Err`, unless you explicitly return RenderError
218    /// inside templates
219    ///
220    /// ```
221    /// use sailfish::{TemplateOnce, TemplateMut, Template};
222    /// use sailfish::runtime::Buffer;
223    ///
224    /// # pub struct HelloTemplate {
225    /// #   messages: Vec<String>,
226    /// # }
227    /// #
228    /// # impl TemplateOnce for HelloTemplate {
229    /// #     fn render_once(self) -> Result<String, sailfish::RenderError> {
230    /// #         Ok(String::new())
231    /// #     }
232    /// #
233    /// #     fn render_once_to(self, buf: &mut Buffer)
234    /// #             -> Result<(), sailfish::RenderError> {
235    /// #         Ok(())
236    /// #     }
237    /// # }
238    /// #
239    /// # impl TemplateMut for HelloTemplate {
240    /// #     fn render_mut(&mut self) -> Result<String, sailfish::RenderError> {
241    /// #         Ok(String::new())
242    /// #     }
243    /// #
244    /// #     fn render_mut_to(&mut self, buf: &mut Buffer)
245    /// #             -> Result<(), sailfish::RenderError> {
246    /// #         Ok(())
247    /// #     }
248    /// # }
249    /// #
250    /// # impl Template for HelloTemplate {
251    /// #     fn render(&self) -> Result<String, sailfish::RenderError> {
252    /// #         Ok(String::new())
253    /// #     }
254    /// #
255    /// #     fn render_to(&self, buf: &mut Buffer)
256    /// #             -> Result<(), sailfish::RenderError> {
257    /// #         Ok(())
258    /// #     }
259    /// # }
260    /// #
261    /// let tpl = HelloTemplate {
262    ///     messages: vec!["foo".to_string()]
263    /// };
264    ///
265    /// // custom pre-allocation
266    /// let mut buffer = Buffer::with_capacity(100);
267    /// tpl.render_to(&mut buffer).unwrap();
268    /// ```
269    fn render_to(&self, buf: &mut Buffer) -> Result<(), RenderError>;
270}