melib/
lib.rs

1/*
2 * meli - lib.rs
3 *
4 * Copyright 2017 Manos Pitsidianakis
5 *
6 * This file is part of meli.
7 *
8 * meli is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * meli is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with meli. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#![deny(
23    rustdoc::redundant_explicit_links,
24    unsafe_op_in_unsafe_fn,
25    /* groups */
26    clippy::correctness,
27    clippy::suspicious,
28    clippy::complexity,
29    clippy::perf,
30    clippy::cargo,
31    clippy::nursery,
32    clippy::style,
33    /* restriction */
34    clippy::dbg_macro,
35    clippy::rc_buffer,
36    clippy::as_underscore,
37    clippy::assertions_on_result_states,
38    /* rustdoc */
39    rustdoc::broken_intra_doc_links,
40    /* pedantic */
41    //clippy::cast_lossless,
42    //clippy::cast_possible_wrap,
43    //clippy::ptr_as_ptr,
44    //clippy::bool_to_int_with_if,
45    clippy::doc_markdown,
46    clippy::expect_fun_call,
47    clippy::or_fun_call,
48    clippy::borrow_as_ptr,
49    clippy::case_sensitive_file_extension_comparisons,
50    //clippy::cast_lossless,
51    //clippy::cast_ptr_alignment,
52    clippy::large_futures,
53    clippy::waker_clone_wake,
54    clippy::unused_enumerate_index,
55    clippy::unnecessary_fallible_conversions,
56    clippy::struct_field_names,
57    clippy::manual_hash_one,
58    clippy::into_iter_without_iter,
59)]
60#![allow(
61    clippy::option_if_let_else,
62    clippy::missing_const_for_fn,
63    clippy::significant_drop_tightening,
64    clippy::multiple_crate_versions,
65    clippy::significant_drop_in_scrutinee,
66    clippy::cognitive_complexity
67)]
68/* Source Code Annotation Tags:
69 *
70 * Global tags (in tagref format <https://github.com/stepchowfun/tagref>) for source code
71 * annotation:
72 *
73 * - [tag:needs_unit_test]
74 * - [tag:needs_user_doc]
75 * - [tag:needs_dev_doc]
76 * - [tag:FIXME]
77 * - [tag:TODO]
78 * - [tag:VERIFY] Verify whether this is the correct way to do something
79 * - [tag:DEBT] Technical debt
80 * - [tag:msrv] Code that might need change when MSRV is bumped
81 */
82#![doc = include_str!("../README.md")]
83//!
84//! ## Description
85//!
86//! A crate that performs mail client operations such as
87//! - Hold an [`Envelope`] with methods convenient for mail client use. (see
88//!   module [`email`])
89//! - Abstract through mail storages through the [`MailBackend`] trait, and
90//!   handle read/writes/updates through it. (see module [`backends`])
91//! - Decode attachments (see module [`email::attachments`])
92//! - Create new mail (see [`email::Draft`](email::compose::Draft))
93//! - Send mail with an SMTP client (see module [`smtp`])
94//! - Manage contacts (see module [`contacts`])
95//! - Build thread structures out of a list of mail via their `In-Reply-To` and
96//!   `References` header values (see module [`thread`])
97//!
98//! Other exports are
99//! - Basic mail account configuration to use with [`backends`] (see module
100//!   [`conf`])
101//! - A `debug` macro that works like `std::dbg` but for multiple threads. (see
102//!   [`debug` macro](debug!))
103
104#[macro_use]
105pub mod dbg {
106
107    #[allow(clippy::redundant_closure)]
108    #[macro_export]
109    macro_rules! debug {
110        ($val:literal) => {
111            {
112                if cfg!(feature="debug-tracing") {
113                    $crate::log::debug!($val);
114                }
115                $val
116            }
117        };
118        ($val:expr) => {
119            if cfg!(feature="debug-tracing") {
120                let stringify = stringify!($val);
121                // Use of `match` here is intentional because it affects the lifetimes
122                // of temporaries - https://stackoverflow.com/a/48732525/1063961
123                match $val {
124                    tmp => {
125                        $crate::log::debug!("{} = {:?}", stringify, tmp);
126                        tmp
127                    }
128                }
129            } else {
130                $val
131            }
132        };
133        ($fmt:literal, $($arg:tt)*) => {
134            if cfg!(feature="debug-tracing") {
135                $crate::log::debug!($fmt, $($arg)*);
136            }
137        };
138    }
139}
140
141pub mod text;
142
143pub use utils::{
144    datetime::UnixTimestamp,
145    logging::{LogLevel, StderrLogger},
146    SortField, SortOrder,
147};
148
149pub mod contacts;
150pub use contacts::*;
151pub mod backends;
152pub use backends::*;
153mod collection;
154pub mod sieve;
155pub use collection::*;
156pub mod conf;
157pub use conf::*;
158pub mod email;
159pub use email::*;
160pub mod error;
161pub use error::*;
162pub mod thread;
163pub use thread::*;
164pub mod search;
165
166#[macro_use]
167pub mod utils;
168
169#[cfg(feature = "gpgme")]
170pub mod gpgme;
171#[cfg(feature = "imap")]
172pub mod imap;
173#[cfg(feature = "jmap")]
174pub mod jmap;
175#[cfg(feature = "maildir")]
176pub mod maildir;
177pub mod mbox;
178#[cfg(feature = "nntp")]
179pub mod nntp;
180#[cfg(feature = "notmuch")]
181pub mod notmuch;
182#[cfg(feature = "smtp")]
183pub mod smtp;
184
185#[macro_use]
186extern crate serde_derive;
187pub extern crate log;
188/* parser */
189extern crate data_encoding;
190pub extern crate nom;
191
192#[macro_use]
193extern crate bitflags;
194pub extern crate futures;
195#[allow(unused_imports)]
196#[macro_use]
197pub extern crate indexmap;
198#[cfg(feature = "sqlite3")]
199pub extern crate rusqlite;
200pub extern crate serde_path_to_error;
201pub extern crate smallvec;
202pub extern crate smol;
203pub extern crate uuid;
204
205#[derive(Clone, Copy, Debug)]
206#[repr(transparent)]
207pub struct BytesDisplay(pub usize);
208
209impl BytesDisplay {
210    pub const KILOBYTE: f64 = 1024.0;
211    pub const MEGABYTE: f64 = Self::KILOBYTE * 1024.0;
212    pub const GIGABYTE: f64 = Self::MEGABYTE * 1024.0;
213    pub const PETABYTE: f64 = Self::GIGABYTE * 1024.0;
214}
215
216impl std::fmt::Display for BytesDisplay {
217    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
218        let bytes: f64 = self.0 as f64;
219        if bytes == 0.0 {
220            write!(fmt, "0")
221        } else if bytes < Self::KILOBYTE {
222            write!(fmt, "{bytes:.2} bytes")
223        } else if bytes < Self::MEGABYTE {
224            write!(fmt, "{:.2} KiB", bytes / Self::KILOBYTE)
225        } else if bytes < Self::GIGABYTE {
226            write!(fmt, "{:.2} MiB", bytes / Self::MEGABYTE)
227        } else if bytes < Self::PETABYTE {
228            write!(fmt, "{:.2} GiB", bytes / Self::GIGABYTE)
229        } else {
230            write!(fmt, "{:.2} PiB", bytes / Self::PETABYTE)
231        }
232    }
233}
234
235pub use utils::shellexpand::ShellExpandTrait;