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}