summaryrefslogtreecommitdiffstats
path: root/template/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'template/src/lib.rs')
-rw-r--r--template/src/lib.rs202
1 files changed, 98 insertions, 104 deletions
diff --git a/template/src/lib.rs b/template/src/lib.rs
index be3ce45..f0763fa 100644
--- a/template/src/lib.rs
+++ b/template/src/lib.rs
@@ -1,63 +1,52 @@
extern crate failure;
-extern crate serde;
extern crate futures;
+#[cfg(feature = "handlebars")]
+extern crate handlebars as hbs;
extern crate mail_core;
extern crate mail_headers;
-extern crate vec1;
-extern crate toml;
extern crate maybe_owned;
-#[cfg(feature="handlebars")]
-extern crate handlebars as hbs;
+extern crate serde;
+extern crate toml;
+extern crate vec1;
-#[cfg(all(feature="handlebars", not(feature="handlebars-bindings")))]
+#[cfg(all(feature = "handlebars", not(feature = "handlebars-bindings")))]
compile_error!("use feature `handlebars-bindings` instead of opt-dep-auto-feature `handlebars`");
use std::{
- fs,
collections::HashMap,
fmt::Debug,
+ fs,
+ ops::Deref,
path::{Path, PathBuf},
- ops::Deref
};
-use serde::{
- Serialize,
- Deserialize
-};
use failure::Error;
use futures::{
- Future, Poll, Async,
- try_ready,
- future::{self, Join, Either}
+ future::{self, Either, Join},
+ try_ready, Async, Future, Poll,
};
-use vec1::Vec1;
use maybe_owned::MaybeOwned;
+use serde::{Deserialize, Serialize};
+use vec1::Vec1;
use mail_core::{
- Resource,
- Data, Metadata,
- Context, ResourceContainerLoadingFuture,
- compose::{MailParts, BodyPart},
- Mail
-};
-use mail_headers::{
- HeaderKind, Header,
- header_components::MediaType,
- headers
+ compose::{BodyPart, MailParts},
+ Context, Data, Mail, Metadata, Resource, ResourceContainerLoadingFuture,
};
+use mail_headers::{header_components::MediaType, headers, Header, HeaderKind};
+mod additional_cid;
mod base_dir;
+pub mod error;
mod path_rebase;
-mod additional_cid;
pub mod serde_impl;
-pub mod error;
-#[cfg(feature="handlebars")]
+#[cfg(feature = "handlebars")]
pub mod handlebars;
+pub use self::additional_cid::*;
pub use self::base_dir::*;
pub use self::path_rebase::*;
-pub use self::additional_cid::*;
/// Trait used to bind/implement template engines.
pub trait TemplateEngine: Sized {
@@ -65,11 +54,12 @@ pub trait TemplateEngine: Sized {
type LazyBodyTemplate: PathRebaseable + Debug + Send + Serialize + for<'a> Deserialize<'a>;
- fn load_body_template(&mut self, tmpl: Self::LazyBodyTemplate)
- -> Result<BodyTemplate<Self>, Error>;
+ fn load_body_template(
+ &mut self,
+ tmpl: Self::LazyBodyTemplate,
+ ) -> Result<BodyTemplate<Self>, Error>;
- fn load_subject_template(&mut self, template_string: String)
- -> Result<Self::Id, Error>;
+ fn load_subject_template(&mut self, template_string: String) -> Result<Self::Id, Error>;
}
/// Additional trait a template engine needs to implement for the types it can process as input.
@@ -77,12 +67,11 @@ pub trait TemplateEngine: Sized {
/// This could for example be implemented in a wild card impl for the template engine for
/// any data `D` which implements `Serialize`.
pub trait TemplateEngineCanHandleData<D>: TemplateEngine {
-
fn render<'r, 'a>(
&'r self,
id: &'r Self::Id,
data: &'r D,
- additional_cids: AdditionalCIds<'r>
+ additional_cids: AdditionalCIds<'r>,
) -> Result<String, Error>;
}
@@ -93,45 +82,48 @@ pub trait TemplateEngineCanHandleData<D>: TemplateEngine {
pub fn load_toml_template_from_path<TE, C>(
engine: TE,
path: PathBuf,
- ctx: &C
-) -> impl Future<Item=Template<TE>, Error=Error>
- where TE: TemplateEngine + 'static, C: Context
+ ctx: &C,
+) -> impl Future<Item = Template<TE>, Error = Error>
+where
+ TE: TemplateEngine + 'static,
+ C: Context,
{
-
let ctx2 = ctx.clone();
ctx.offload_fn(move || {
let content = fs::read_to_string(&path)?;
let base: serde_impl::TemplateBase<TE> = toml::from_str(&content)?;
- let base_dir = path.parent().unwrap_or_else(||Path::new("."));
+ let base_dir = path.parent().unwrap_or_else(|| Path::new("."));
let base_dir = CwdBaseDir::from_path(base_dir)?;
Ok((base, base_dir))
- }).and_then(move |(base, base_dir)| base.load(engine, base_dir, &ctx2))
+ })
+ .and_then(move |(base, base_dir)| base.load(engine, base_dir, &ctx2))
}
/// Load a template as described in a toml string;
pub fn load_toml_template_from_str<TE, C>(
engine: TE,
content: &str,
- ctx: &C
-) -> impl Future<Item=Template<TE>, Error=Error>
- where TE: TemplateEngine, C: Context
+ ctx: &C,
+) -> impl Future<Item = Template<TE>, Error = Error>
+where
+ TE: TemplateEngine,
+ C: Context,
{
- let base: serde_impl::TemplateBase<TE> =
- match toml::from_str(content) {
- Ok(base) => base,
- Err(err) => { return Either::B(future::err(Error::from(err))); }
- };
+ let base: serde_impl::TemplateBase<TE> = match toml::from_str(content) {
+ Ok(base) => base,
+ Err(err) => {
+ return Either::B(future::err(Error::from(err)));
+ }
+ };
- let base_dir =
- match CwdBaseDir::from_path(Path::new(".")) {
- Ok(base_dir) => base_dir,
- Err(err) => { return Either::B(future::err(Error::from(err))) }
- };
+ let base_dir = match CwdBaseDir::from_path(Path::new(".")) {
+ Ok(base_dir) => base_dir,
+ Err(err) => return Either::B(future::err(Error::from(err))),
+ };
Either::A(base.load(engine, base_dir, ctx))
}
-
/// A Mail template.
#[derive(Debug)]
pub struct Template<TE: TemplateEngine> {
@@ -149,7 +141,8 @@ pub struct Template<TE: TemplateEngine> {
}
impl<TE> Template<TE>
- where TE: TemplateEngine
+where
+ TE: TemplateEngine,
{
pub fn inline_embeddings(&self) -> &HashMap<String, Resource> {
&self.embeddings
@@ -172,17 +165,17 @@ impl<TE> Template<TE>
}
}
-
/// Represents one of potentially many alternate bodies in a template.
#[derive(Debug)]
pub struct BodyTemplate<TE: TemplateEngine> {
pub template_id: TE::Id,
pub media_type: MediaType,
- pub inline_embeddings: HashMap<String, Resource>
+ pub inline_embeddings: HashMap<String, Resource>,
}
impl<TE> BodyTemplate<TE>
- where TE: TemplateEngine
+where
+ TE: TemplateEngine,
{
pub fn template_id(&self) -> &TE::Id {
&self.template_id
@@ -200,11 +193,12 @@ impl<TE> BodyTemplate<TE>
/// Represents a template used for generating the subject of a mail.
#[derive(Debug)]
pub struct Subject<TE: TemplateEngine> {
- template_id: TE::Id
+ template_id: TE::Id,
}
impl<TE> Subject<TE>
- where TE: TemplateEngine
+where
+ TE: TemplateEngine,
{
pub fn template_id(&self) -> &TE::Id {
&self.template_id
@@ -218,13 +212,20 @@ impl<TE> Subject<TE>
///
/// This trait should not be implemented by hand.
pub trait TemplateExt<TE, D>
- where TE: TemplateEngine + TemplateEngineCanHandleData<D>
+where
+ TE: TemplateEngine + TemplateEngineCanHandleData<D>,
{
-
- fn render_to_mail_parts<'r>(&self, data: LoadedTemplateData<'r, D>, ctx: &impl Context)
- -> Result<(MailParts, Header<headers::Subject>), Error>;
-
- fn render<'r>(&self, data: LoadedTemplateData<'r, D>, ctx: &impl Context) -> Result<Mail, Error> {
+ fn render_to_mail_parts<'r>(
+ &self,
+ data: LoadedTemplateData<'r, D>,
+ ctx: &impl Context,
+ ) -> Result<(MailParts, Header<headers::Subject>), Error>;
+
+ fn render<'r>(
+ &self,
+ data: LoadedTemplateData<'r, D>,
+ ctx: &impl Context,
+ ) -> Result<Mail, Error> {
let (parts, subject) = self.render_to_mail_parts(data, ctx)?;
let mut mail = parts.compose();
mail.insert_header(subject);
@@ -232,24 +233,24 @@ pub trait TemplateExt<TE, D>
}
}
-
impl<TE, D> TemplateExt<TE, D> for Template<TE>
- where TE: TemplateEngine + TemplateEngineCanHandleData<D>
+where
+ TE: TemplateEngine + TemplateEngineCanHandleData<D>,
{
- fn render_to_mail_parts<'r>(&self, data: LoadedTemplateData<'r, D>, ctx: &impl Context)
- -> Result<(MailParts, Header<headers::Subject>), Error>
- {
+ fn render_to_mail_parts<'r>(
+ &self,
+ data: LoadedTemplateData<'r, D>,
+ ctx: &impl Context,
+ ) -> Result<(MailParts, Header<headers::Subject>), Error> {
let TemplateData {
data,
inline_embeddings,
- mut attachments
+ mut attachments,
} = data.into();
- let subject = self.engine().render(
- self.subject_template_id(),
- &data,
- AdditionalCIds::new(&[])
- )?;
+ let subject =
+ self.engine()
+ .render(self.subject_template_id(), &data, AdditionalCIds::new(&[]))?;
let subject = headers::Subject::auto_body(subject)?;
@@ -262,8 +263,8 @@ impl<TE, D> TemplateExt<TE, D> for Template<TE>
AdditionalCIds::new(&[
&inline_embeddings,
body.inline_embeddings(),
- self.inline_embeddings()
- ])
+ self.inline_embeddings(),
+ ]),
)?;
let data = Data::new(
@@ -271,19 +272,16 @@ impl<TE, D> TemplateExt<TE, D> for Template<TE>
Metadata {
file_meta: Default::default(),
media_type: body.media_type().clone(),
- content_id: ctx.generate_content_id()
- }
+ content_id: ctx.generate_content_id(),
+ },
);
- let inline_embeddings = body.inline_embeddings()
- .values()
- .cloned()
- .collect();
+ let inline_embeddings = body.inline_embeddings().values().cloned().collect();
bodies.push(BodyPart {
resource: Resource::Data(data),
inline_embeddings,
- attachments: Vec::new()
+ attachments: Vec::new(),
});
}
@@ -296,13 +294,13 @@ impl<TE, D> TemplateExt<TE, D> for Template<TE>
}
}
- inline_embeddings_vec.extend(inline_embeddings.into_iter().map(|(_,v)|v));
+ inline_embeddings_vec.extend(inline_embeddings.into_iter().map(|(_, v)| v));
let parts = MailParts {
//UNWRAP_SAFE (complexly mapping a Vec1 is safe)
alternative_bodies: Vec1::try_from_vec(bodies).unwrap(),
inline_embeddings: inline_embeddings_vec,
- attachments
+ attachments,
};
Ok((parts, subject))
@@ -310,18 +308,17 @@ impl<TE, D> TemplateExt<TE, D> for Template<TE>
}
pub struct TemplateData<'a, D: 'a> {
- pub data: MaybeOwned<'a, D>,
+ pub data: MaybeOwned<'a, D>,
pub attachments: Vec<Resource>,
- pub inline_embeddings: HashMap<String, Resource>
+ pub inline_embeddings: HashMap<String, Resource>,
}
impl<'a, D> TemplateData<'a, D> {
-
pub fn load(self, ctx: &impl Context) -> DataLoadingFuture<'a, D> {
let TemplateData {
data,
attachments,
- inline_embeddings
+ inline_embeddings,
} = self;
let loading_fut = Resource::load_container(inline_embeddings, ctx)
@@ -329,7 +326,7 @@ impl<'a, D> TemplateData<'a, D> {
DataLoadingFuture {
payload: Some(data),
- loading_fut
+ loading_fut,
}
}
}
@@ -338,7 +335,7 @@ impl<D> From<D> for TemplateData<'static, D> {
TemplateData {
data: data.into(),
attachments: Default::default(),
- inline_embeddings: Default::default()
+ inline_embeddings: Default::default(),
}
}
}
@@ -348,7 +345,7 @@ impl<'a, D> From<&'a D> for TemplateData<'a, D> {
TemplateData {
data: data.into(),
attachments: Default::default(),
- inline_embeddings: Default::default()
+ inline_embeddings: Default::default(),
}
}
}
@@ -387,8 +384,8 @@ pub struct DataLoadingFuture<'a, D: 'a> {
payload: Option<MaybeOwned<'a, D>>,
loading_fut: Join<
ResourceContainerLoadingFuture<HashMap<String, Resource>>,
- ResourceContainerLoadingFuture<Vec<Resource>>
- >
+ ResourceContainerLoadingFuture<Vec<Resource>>,
+ >,
}
impl<'a, D> Future for DataLoadingFuture<'a, D> {
@@ -396,10 +393,7 @@ impl<'a, D> Future for DataLoadingFuture<'a, D> {
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
- let (
- inline_embeddings,
- attachments
- ) = try_ready!(self.loading_fut.poll());
+ let (inline_embeddings, attachments) = try_ready!(self.loading_fut.poll());
//UNWRAP_SAFE only non if polled after resolved
let data = self.payload.take().unwrap();
@@ -407,7 +401,7 @@ impl<'a, D> Future for DataLoadingFuture<'a, D> {
let inner = TemplateData {
data,
inline_embeddings,
- attachments
+ attachments,
};
Ok(Async::Ready(LoadedTemplateData(inner)))