-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathlib.rs
104 lines (88 loc) · 3.46 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! # Importer
//!
//! This crate is responsible for importing different email formats (or email storage formats)
//! by reading and parsing the data and writing it into a database (which is defined as a
//! generic type but most probably the `ps-database` module).
//!
//! Currently, the importer requires the construction of a specific type as well as the
//! configuration of the importer format in a configuration.
//!
//! ``` rs
//! https://github.com/terhechte/postsack/issues/11
//! let path = "tests/resources/mbox";
//! let config =
//! ps_core::Config::new(None, path, vec!["".to_string()], ps_core::FormatType::Mbox).expect("Config");
//! let importer = mbox_importer(config.clone());
//!
//! // Next, crate a database and run the importer
//! // let database = Database::new(&config.database_path).unwrap();
//! // let (_receiver, handle) = importer.import(database).unwrap();
//! ```
use ps_core::eyre::Result;
pub(crate) mod formats;
use formats::{shared, ImporterFormat};
use std::{path::PathBuf, thread::JoinHandle};
use ps_core::{
crossbeam_channel::unbounded, Config, DatabaseLike, FormatType, Importerlike, Message,
MessageReceiver,
};
pub struct Importer<Format: ImporterFormat> {
config: Config,
format: Format,
}
impl<Format: ImporterFormat + 'static> Importer<Format> {
pub fn new(config: Config, format: Format) -> Self {
Self { config, format }
}
}
impl<Format: ImporterFormat + 'static> Importerlike for Importer<Format> {
fn import<Database: DatabaseLike + 'static>(
self,
database: Database,
) -> Result<(MessageReceiver, JoinHandle<Result<()>>)> {
let Importer { format, .. } = self;
let (sender, receiver) = unbounded();
let config = self.config;
let handle: JoinHandle<Result<()>> = std::thread::spawn(move || {
let outer_sender = sender.clone();
let processed = move || {
let emails = format.emails(&config, sender.clone())?;
let processed =
shared::database::into_database(&config, emails, sender.clone(), database)?;
Ok(processed)
};
let result = processed();
// Send the error away and map it to a crossbeam channel error
match result {
Ok(_) => Ok(()),
Err(e) => match outer_sender.send(Message::Error(e)) {
Ok(_) => Ok(()),
Err(e) => Err(ps_core::eyre::Report::new(e)),
},
}
});
Ok((receiver, handle))
}
}
pub fn gmail_importer(config: Config) -> Importer<formats::Gmail> {
Importer::new(config, formats::Gmail::default())
}
pub fn applemail_importer(config: Config) -> Importer<formats::AppleMail> {
Importer::new(config, formats::AppleMail::default())
}
pub fn mbox_importer(config: Config) -> Importer<formats::Mbox> {
Importer::new(config, formats::Mbox::default())
}
#[cfg(not(target_os = "windows"))]
pub fn maildir_importer(config: Config) -> Importer<formats::Maildir> {
Importer::new(config, formats::Maildir::default())
}
pub fn default_path(format: &FormatType) -> Option<PathBuf> {
match format {
FormatType::AppleMail => formats::AppleMail::default_path(),
FormatType::GmailVault => formats::Gmail::default_path(),
FormatType::Mbox => formats::Mbox::default_path(),
#[cfg(not(target_os = "windows"))]
FormatType::Maildir => formats::Maildir::default_path(),
}
}