mail_core/default_impl/
simple_context.rs

1//! This module provides a type alias and constructor function for an simple context impl.
2//!
3//! It used the `FsResourceLoader` and `CpuPool` with a `CompositeContext`.
4//!
5//! Note this module is only available if the `default_impl_cpupool` feature
6//! is enabled.
7//!
8//! # Example
9//!
10//! ```
11//! # extern crate mail_core as mail;
12//! # extern crate mail_headers as headers;
13//! # use headers::header_components::Domain;
14//! # // It's re-exported in the facade under `default_impl`.
15//! # use std::str::FromStr;
16//! use mail::default_impl::simple_context;
17//!
18//! # fn main() {
19//! //TODO[FEAT]: use parse once the `Domain` component implements `FromStr`.
20//! //let domain = "example.com".parse().unwrap();
21//! let domain = Domain::from_unchecked("example.com".to_owned());
22//! // This normally should be world unique for any usage with the same domain.
23//! // This is necessary to generate `Content-Id` and `Message-Id` correctly.
24//! let ascii_unique_part = "xm3r2u".parse().unwrap();
25//! let ctx = simple_context::new(domain, ascii_unique_part).unwrap();
26//! # }
27//! ```
28//!
29use std::io;
30
31use soft_ascii_string::SoftAsciiString;
32use futures_cpupool::{Builder, CpuPool};
33
34use internals::error::EncodingError;
35use headers::header_components::Domain;
36
37use ::context::CompositeContext;
38use ::default_impl::{FsResourceLoader, HashedIdGen};
39
40/// Error returned when creating a "simple_context" fails.
41#[derive(Debug, Fail)]
42pub enum ContextSetupError {
43    /// Reading the env variables failed.
44    ///
45    /// (Mainly getting the current working dir failed).
46    #[fail(display="{}", _0)]
47    ReadingEnv(io::Error),
48
49    /// Punny encoding a non us-ascii domain failed.
50    #[fail(display="{}", _0)]
51    PunyCodingDomain(EncodingError)
52}
53
54/// Type Alias for a the type returned by `simple_context::new`.
55pub type Context = CompositeContext<FsResourceLoader, CpuPool, HashedIdGen>;
56
57/// create a new CompositeContext<FsResourceLoader, CpuPool, HashedIdGen>
58///
59/// It uses the current working directory as root for the `FsResourceLoader`,
60/// and the default settings for the `CpuPool`, both the `domain` and
61/// `unique_part` are passed to the `HashedIdGen::new` constructor.
62///
63/// Note that the combination of `unique_part` and `domain` should be world
64/// unique. This is needed to generate `Content-Id` and `Message-Id` reliably
65/// correctly. This means if you run multiple instances of softer using a context
66/// or you create multiple contexts they should _not_ use the same `unique_part`
67/// under any circumstances (expect if they use different domains, but then you
68/// also should only use domain you actually own).
69pub fn new(domain: Domain, unique_part: SoftAsciiString) -> Result<Context, ContextSetupError> {
70    let resource_loader = FsResourceLoader
71        ::with_cwd_root()
72        .map_err(|err| ContextSetupError::ReadingEnv(err))?;
73
74    let cpu_pool = Builder::new().create();
75
76    let id_gen = HashedIdGen
77        ::new(domain, unique_part)
78        .map_err(|err| ContextSetupError::PunyCodingDomain(err))?;
79
80    Ok(CompositeContext::new(
81        resource_loader,
82        cpu_pool,
83        id_gen,
84    ))
85}