diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-09-21 21:23:06 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-09-21 21:29:33 +0300 |
commit | 6e75160b70496d61988fee31d4c28e47f367a518 (patch) | |
tree | 6d963625b43c43033efdc0f9b22c551fb6d5a481 | |
parent | f066f35410cd631955cff4c5ae1ec49f9826bb36 (diff) |
melib: turn unicode algos and backends into features
-rw-r--r-- | melib/Cargo.toml | 18 | ||||
-rw-r--r-- | melib/src/backends.rs | 41 | ||||
-rw-r--r-- | melib/src/email/compose/mime.rs | 132 | ||||
-rw-r--r-- | melib/src/error.rs | 2 | ||||
-rw-r--r-- | melib/src/lib.rs | 2 | ||||
-rw-r--r-- | melib/src/thread.rs | 65 |
6 files changed, 191 insertions, 69 deletions
diff --git a/melib/Cargo.toml b/melib/Cargo.toml index b76f43d0..441353c2 100644 --- a/melib/Cargo.toml +++ b/melib/Cargo.toml @@ -12,16 +12,24 @@ crossbeam = "0.7.2" data-encoding = "2.1.1" encoding = "0.2.33" fnv = "1.0.3" -memmap = "0.5.2" +memmap = { version = "0.5.2", optional = true } nom = "3.2.0" -notify = "4.0.1" -notify-rust = "^3" +notify = { version = "4.0.1", optional = true } +notify-rust = { version = "^3", optional = true } termion = "1.5.1" xdg = "2.1.0" -native-tls = "0.2" +native-tls = { version ="0.2", optional=true } serde = "1.0.71" serde_derive = "1.0.71" bincode = "1.0.1" uuid = { version = "0.6", features = ["serde", "v4"] } -text_processing = { path = "../text_processing", version = "*" } +text_processing = { path = "../text_processing", version = "*", optional= true } libc = {version = "0.2.59", features = ["extra_traits",]} + +[features] +default = ["unicode_algorithms", "imap_backend", "maildir_backend", "mbox_backend"] + +unicode_algorithms = ["text_processing"] +imap_backend = ["native-tls"] +maildir_backend = ["notify", "notify-rust", "memmap"] +mbox_backend = ["notify", "notify-rust", "memmap"] diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 57cee63a..06bdf251 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -18,16 +18,22 @@ * You should have received a copy of the GNU General Public License * along with meli. If not, see <http://www.gnu.org/licenses/>. */ +#[cfg(feature = "imap_backend")] pub mod imap; +#[cfg(feature = "maildir_backend")] pub mod maildir; +#[cfg(feature = "mbox_backend")] pub mod mbox; +#[cfg(feature = "imap_backend")] pub use self::imap::ImapType; use crate::async_workers::*; use crate::conf::AccountSettings; use crate::error::{MeliError, Result}; -//use mailbox::backends::imap::ImapType; + +#[cfg(feature = "maildir_backend")] use self::maildir::MaildirType; +#[cfg(feature = "mbox_backend")] use self::mbox::MboxType; use super::email::{Envelope, EnvelopeHash, Flag}; use std::fmt; @@ -57,18 +63,27 @@ impl Backends { let mut b = Backends { map: FnvHashMap::with_capacity_and_hasher(1, Default::default()), }; - b.register( - "maildir".to_string(), - Box::new(|| Box::new(|f, i| Box::new(MaildirType::new(f, i)))), - ); - b.register( - "mbox".to_string(), - Box::new(|| Box::new(|f, i| Box::new(MboxType::new(f, i)))), - ); - b.register( - "imap".to_string(), - Box::new(|| Box::new(|f, i| Box::new(ImapType::new(f, i)))), - ); + #[cfg(feature = "maildir_backend")] + { + b.register( + "maildir".to_string(), + Box::new(|| Box::new(|f, i| Box::new(MaildirType::new(f, i)))), + ); + } + #[cfg(feature = "mbox_backend")] + { + b.register( + "mbox".to_string(), + Box::new(|| Box::new(|f, i| Box::new(MboxType::new(f, i)))), + ); + } + #[cfg(feature = "imap_backend")] + { + b.register( + "imap".to_string(), + Box::new(|| Box::new(|f, i| Box::new(ImapType::new(f, i)))), + ); + } b } diff --git a/melib/src/email/compose/mime.rs b/melib/src/email/compose/mime.rs index 081e11d1..371c741b 100644 --- a/melib/src/email/compose/mime.rs +++ b/melib/src/email/compose/mime.rs @@ -1,22 +1,51 @@ use super::*; + +#[cfg(feature = "unicode_algorithms")] use text_processing::grapheme_clusters::Graphemes; pub fn encode_header(value: &str) -> String { let mut ret = String::with_capacity(value.len()); - let graphemes = value.graphemes_indices(); let mut is_current_window_ascii = true; let mut current_window_start = 0; - for (idx, g) in graphemes { - match (g.is_ascii(), is_current_window_ascii) { - (true, true) => { - ret.push_str(g); - } - (true, false) => { - /* If !g.is_whitespace() - * - * Whitespaces inside encoded tokens must be greedily taken, - * instead of splitting each non-ascii word into separate encoded tokens. */ - if !g.split_whitespace().collect::<Vec<&str>>().is_empty() { + #[cfg(feature = "unicode_algorithms")] + { + let graphemes = value.graphemes_indices(); + for (idx, g) in graphemes { + match (g.is_ascii(), is_current_window_ascii) { + (true, true) => { + ret.push_str(g); + } + (true, false) => { + /* If !g.is_whitespace() + * + * Whitespaces inside encoded tokens must be greedily taken, + * instead of splitting each non-ascii word into separate encoded tokens. */ + if !g.split_whitespace().collect::<Vec<&str>>().is_empty() { + ret.push_str(&format!( + "=?UTF-8?B?{}?=", + BASE64_MIME + .encode(value[current_window_start..idx].as_bytes()) + .trim() + )); + if idx != value.len() - 1 { + ret.push(' '); + } + is_current_window_ascii = true; + current_window_start = idx; + ret.push_str(g); + } + } + (false, true) => { + current_window_start = idx; + is_current_window_ascii = false; + } + /* RFC2047 recommends: + * 'While there is no limit to the length of a multiple-line header field, each line of + * a header field that contains one or more 'encoded-word's is limited to 76 + * characters.' + * This is a rough compliance. + */ + (false, false) if (((4 * (idx - current_window_start) / 3) + 3) & !3) > 33 => { ret.push_str(&format!( "=?UTF-8?B?{}?=", BASE64_MIME @@ -26,34 +55,67 @@ pub fn encode_header(value: &str) -> String { if idx != value.len() - 1 { ret.push(' '); } - is_current_window_ascii = true; current_window_start = idx; - ret.push_str(g); } + (false, false) => {} } - (false, true) => { - current_window_start = idx; - is_current_window_ascii = false; - } - /* RFC2047 recommends: - * 'While there is no limit to the length of a multiple-line header field, each line of - * a header field that contains one or more 'encoded-word's is limited to 76 - * characters.' - * This is a rough compliance. - */ - (false, false) if (((4 * (idx - current_window_start) / 3) + 3) & !3) > 33 => { - ret.push_str(&format!( - "=?UTF-8?B?{}?=", - BASE64_MIME - .encode(value[current_window_start..idx].as_bytes()) - .trim() - )); - if idx != value.len() - 1 { - ret.push(' '); + } + } + #[cfg(not(feature = "unicode_algorithms"))] + { + /* TODO: test this. If it works as fine as the one above, there's no need to keep the above + * implementation.*/ + let mut idx = 0; + for g in value.chars() { + match (g.is_ascii(), is_current_window_ascii) { + (true, true) => { + ret.push(g); + } + (true, false) => { + /* If !g.is_whitespace() + * + * Whitespaces inside encoded tokens must be greedily taken, + * instead of splitting each non-ascii word into separate encoded tokens. */ + if !g.is_whitespace() { + ret.push_str(&format!( + "=?UTF-8?B?{}?=", + BASE64_MIME + .encode(value[current_window_start..idx].as_bytes()) + .trim() + )); + if idx != value.len() - 1 { + ret.push(' '); + } + is_current_window_ascii = true; + current_window_start = idx; + ret.push(g); + } + } + (false, true) => { + current_window_start = idx; + is_current_window_ascii = false; + } + /* RFC2047 recommends: + * 'While there is no limit to the length of a multiple-line header field, each line of + * a header field that contains one or more 'encoded-word's is limited to 76 + * characters.' + * This is a rough compliance. + */ + (false, false) if (((4 * (idx - current_window_start) / 3) + 3) & !3) > 33 => { + ret.push_str(&format!( + "=?UTF-8?B?{}?=", + BASE64_MIME + .encode(value[current_window_start..idx].as_bytes()) + .trim() + )); + if idx != value.len() - 1 { + ret.push(' '); + } + current_window_start = idx; } - current_window_start = idx; + (false, false) => {} } - (false, false) => {} + idx += std::mem::size_of::<char>(); } } /* If the last part of the header value is encoded, it won't be pushed inside the previous for diff --git a/melib/src/error.rs b/melib/src/error.rs index 7d8c0813..3f5ffdca 100644 --- a/melib/src/error.rs +++ b/melib/src/error.rs @@ -118,6 +118,7 @@ impl<T> From<std::sync::PoisonError<T>> for MeliError { } } +#[cfg(feature = "imap_backend")] impl From<native_tls::HandshakeError<std::net::TcpStream>> for MeliError { #[inline] fn from(kind: native_tls::HandshakeError<std::net::TcpStream>) -> MeliError { @@ -125,6 +126,7 @@ impl From<native_tls::HandshakeError<std::net::TcpStream>> for MeliError { } } +#[cfg(feature = "imap_backend")] impl From<native_tls::Error> for MeliError { #[inline] fn from(kind: native_tls::Error) -> MeliError { diff --git a/melib/src/lib.rs b/melib/src/lib.rs index a43f90ed..c908aec9 100644 --- a/melib/src/lib.rs +++ b/melib/src/lib.rs @@ -84,6 +84,7 @@ pub mod dbg { } } +#[cfg(feature = "unicode_algorithms")] extern crate text_processing; #[macro_use] @@ -113,7 +114,6 @@ extern crate nom; extern crate chrono; extern crate data_encoding; extern crate encoding; -extern crate memmap; #[macro_use] extern crate bitflags; diff --git a/melib/src/thread.rs b/melib/src/thread.rs index 0daa2ddf..89981b5b 100644 --- a/melib/src/thread.rs +++ b/melib/src/thread.rs @@ -35,6 +35,8 @@ use crate::email::parser::BytesExt; use crate::email::*; use crate::structs::StackVec; + +#[cfg(feature = "unicode_algorithms")] use text_processing::grapheme_clusters::*; use uuid::Uuid; @@ -504,10 +506,19 @@ impl ThreadNode { buf.get(&probe).map(|n| n.message.as_ref()).unwrap_or(None), buf.get(&child).map(|n| n.message.as_ref()).unwrap_or(None), ) { - (Some(p), Some(c)) => envelopes[p] - .subject() - .split_graphemes() - .cmp(&envelopes[c].subject().split_graphemes()), + (Some(p), Some(c)) => { + #[cfg(feature = "unicode_algorithms")] + { + envelopes[p] + .subject() + .split_graphemes() + .cmp(&envelopes[c].subject().split_graphemes()) + } + #[cfg(not(feature = "unicode_algorithms"))] + { + envelopes[p].subject().cmp(&envelopes[c].subject()) + } + } (Some(_), None) => Ordering::Greater, (None, Some(_)) => Ordering::Less, (None, None) => Ordering::Equal, @@ -523,10 +534,19 @@ impl ThreadNode { buf.get(&probe).map(|n| n.message.as_ref()).unwrap_or(None), buf.get(&child).map(|n| n.message.as_ref()).unwrap_or(None), ) { - (Some(p), Some(c)) => envelopes[c] - .subject() - .split_graphemes() - .cmp(&envelopes[p].subject().split_graphemes()), + (Some(p), Some(c)) => { + #[cfg(feature = "unicode_algorithms")] + { + envelopes[c] + .subject() + .split_graphemes() + .cmp(&envelopes[p].subject().split_graphemes()) + } + #[cfg(not(feature = "unicode_algorithms"))] + { + envelopes[c].subject().cmp(&envelopes[p].subject()) + } + } (Some(_), None) => Ordering::Less, (None, Some(_)) => Ordering::Greater, (None, None) => Ordering::Equal, @@ -1078,9 +1098,16 @@ impl Threads { } let ma = &envelopes[&a.unwrap()]; let mb = &envelopes[&b.unwrap()]; - ma.subject() - .split_graphemes() - .cmp(&mb.subject().split_graphemes()) + #[cfg(feature = "unicode_algorithms")] + { + ma.subject() + .split_graphemes() + .cmp(&mb.subject().split_graphemes()) + } + #[cfg(not(feature = "unicode_algorithms"))] + { + ma.subject().cmp(&mb.subject()) + } } (SortField::Subject, SortOrder::Asc) => { let a = &self.thread_nodes[&a].message(); @@ -1100,10 +1127,18 @@ impl Threads { } let ma = &envelopes[&a.unwrap()]; let mb = &envelopes[&b.unwrap()]; - mb.subject() - .as_ref() - .split_graphemes() - .cmp(&ma.subject().split_graphemes()) + #[cfg(feature = "unicode_algorithms")] + { + mb.subject() + .as_ref() + .split_graphemes() + .cmp(&ma.subject().split_graphemes()) + } + + #[cfg(not(feature = "unicode_algorithms"))] + { + mb.subject().as_ref().cmp(&ma.subject()) + } } }); } |