diff --git a/Cargo.lock b/Cargo.lock index 14d7b487..f67bb3b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -771,6 +771,7 @@ dependencies = [ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "text_processing 0.4.1", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1553,8 +1554,11 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "sourcefile" @@ -1860,6 +1864,7 @@ dependencies = [ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "text_processing 0.4.1", "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1889,7 +1894,7 @@ name = "unicode-normalization" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2298,7 +2303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" diff --git a/melib/Cargo.toml b/melib/Cargo.toml index e7a40533..881e932c 100644 --- a/melib/Cargo.toml +++ b/melib/Cargo.toml @@ -27,6 +27,7 @@ text_processing = { path = "../text_processing", version = "*", optional= true } libc = {version = "0.2.59", features = ["extra_traits",]} reqwest = { version ="0.10.0-alpha.2", optional=true, features = ["json", "blocking" ]} serde_json = { version = "1.0", optional = true, features = ["raw_value",] } +smallvec = { version = "1.1.0", features = ["serde", ] } [features] default = ["unicode_algorithms", "imap_backend", "maildir_backend", "mbox_backend", "vcard"] diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index dd4aad88..de694f53 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -19,6 +19,7 @@ * along with meli. If not, see . */ +use smallvec::SmallVec; #[macro_use] mod protocol_parser; pub use protocol_parser::{UntaggedResponse::*, *}; @@ -677,7 +678,7 @@ impl ImapType { &self, query: String, folder_hash: FolderHash, - ) -> Result> { + ) -> Result> { let folders_lck = self.folders.read()?; let mut response = String::with_capacity(8 * 1024); let mut conn = self.connection.lock()?; @@ -692,7 +693,7 @@ impl ImapType { if l.starts_with("* SEARCH") { use std::iter::FromIterator; let uid_index = self.uid_store.uid_index.lock()?; - return Ok(crate::structs::StackVec::from_iter( + return Ok(SmallVec::from_iter( l["* SEARCH".len()..] .trim() .split_whitespace() diff --git a/melib/src/backends/jmap/protocol.rs b/melib/src/backends/jmap/protocol.rs index 6057a2e9..10bb7092 100644 --- a/melib/src/backends/jmap/protocol.rs +++ b/melib/src/backends/jmap/protocol.rs @@ -21,9 +21,9 @@ use super::folder::JmapFolder; use super::*; -use crate::structs::StackVec; use serde::Serialize; use serde_json::{json, Value}; +use smallvec::SmallVec; use std::collections::hash_map::DefaultHasher; use std::convert::TryFrom; use std::hash::{Hash, Hasher}; @@ -327,10 +327,10 @@ pub fn get( } tag_hash }) - .collect::>(); + .collect::>(); (tags, obj.id.clone(), obj.blob_id.clone()) }) - .collect::, Id, Id)>>(); + .collect::, Id, Id)>>(); drop(tag_lck); let mut ret = list .into_iter() diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs index 8356c840..66666797 100644 --- a/melib/src/backends/notmuch.rs +++ b/melib/src/backends/notmuch.rs @@ -1,3 +1,24 @@ +/* + * meli - notmuch backend + * + * Copyright 2019 - 2020 Manos Pitsidianakis + * + * This file is part of meli. + * + * meli is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * meli is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with meli. If not, see . + */ + use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext}; use crate::backends::FolderHash; use crate::backends::{ @@ -8,8 +29,8 @@ use crate::conf::AccountSettings; use crate::email::{Envelope, EnvelopeHash, Flag}; use crate::error::{MeliError, Result}; use crate::shellexpand::ShellExpandTrait; -use crate::structs::StackVec; use fnv::FnvHashMap; +use smallvec::SmallVec; use std::collections::hash_map::DefaultHasher; use std::collections::BTreeMap; use std::ffi::{CStr, CString}; @@ -229,7 +250,7 @@ impl NotmuchDb { Ok(()) } - pub fn search(&self, query_s: &str) -> Result> { + pub fn search(&self, query_s: &str) -> Result> { let database_lck = self.database.inner.read().unwrap(); let query_str = std::ffi::CString::new(query_s).unwrap(); let query: *mut notmuch_query_t = @@ -247,7 +268,7 @@ impl NotmuchDb { } assert!(!messages.is_null()); let iter = MessageIterator { messages }; - let mut ret = StackVec::new(); + let mut ret = SmallVec::new(); for message in iter { let fs_path = unsafe { notmuch_message_get_filename(message) }; let c_str = unsafe { CStr::from_ptr(fs_path) }; diff --git a/melib/src/collection.rs b/melib/src/collection.rs index 28c9cd32..a5fc0095 100644 --- a/melib/src/collection.rs +++ b/melib/src/collection.rs @@ -1,5 +1,6 @@ use super::*; use crate::backends::FolderHash; +use smallvec::SmallVec; use std::collections::BTreeMap; use std::ops::{Deref, DerefMut}; use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -160,7 +161,7 @@ impl Collection { mut new_envelopes: FnvHashMap, folder_hash: FolderHash, sent_folder: Option, - ) -> Option> { + ) -> Option> { self.sent_folder = sent_folder; for (h, e) in new_envelopes.iter() { self.message_ids.insert(e.message_id().raw().to_vec(), *h); @@ -198,7 +199,7 @@ impl Collection { }); } - let mut ret = StackVec::new(); + let mut ret = SmallVec::new(); let keys = threads.keys().cloned().collect::>(); for t_fh in keys { if t_fh == folder_hash { diff --git a/melib/src/datetime.rs b/melib/src/datetime.rs index 7c56686f..0c89925b 100644 --- a/melib/src/datetime.rs +++ b/melib/src/datetime.rs @@ -61,7 +61,7 @@ pub fn timestamp_to_string(timestamp: UnixTimestamp, fmt: Option<&str>) -> Strin }; let s: CString; unsafe { - let mut vec: Vec = vec![0; 256]; + let mut vec: [u8; 256] = [0; 256]; let ret = strftime( vec.as_mut_ptr() as *mut _, 256, diff --git a/melib/src/email.rs b/melib/src/email.rs index cab8565e..1faff060 100644 --- a/melib/src/email.rs +++ b/melib/src/email.rs @@ -43,6 +43,7 @@ use crate::datetime::UnixTimestamp; use crate::error::{MeliError, Result}; use crate::thread::ThreadHash; +use smallvec::SmallVec; use std::borrow::Cow; use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; @@ -132,7 +133,7 @@ pub struct Envelope { flags: Flag, has_attachments: bool, - labels: crate::structs::StackVec, + labels: SmallVec<[u64; 8]>, } impl fmt::Debug for Envelope { @@ -170,7 +171,7 @@ impl Envelope { hash, has_attachments: false, flags: Flag::default(), - labels: crate::structs::StackVec::new(), + labels: SmallVec::new(), } } @@ -609,11 +610,11 @@ impl Envelope { self.has_attachments } - pub fn labels(&self) -> &crate::structs::StackVec { + pub fn labels(&self) -> &SmallVec<[u64; 8]> { &self.labels } - pub fn labels_mut(&mut self) -> &mut crate::structs::StackVec { + pub fn labels_mut(&mut self) -> &mut SmallVec<[u64; 8]> { &mut self.labels } } diff --git a/melib/src/email/list_management.rs b/melib/src/email/list_management.rs index c4744367..93a14d3d 100644 --- a/melib/src/email/list_management.rs +++ b/melib/src/email/list_management.rs @@ -18,9 +18,10 @@ * You should have received a copy of the GNU General Public License * along with meli. If not, see . */ + use super::parser; use super::Envelope; -use crate::StackVec; +use smallvec::SmallVec; use std::convert::From; #[derive(Debug, Copy)] @@ -46,7 +47,7 @@ impl<'a> From<&'a [u8]> for ListAction<'a> { } impl<'a> ListAction<'a> { - pub fn parse_options_list(input: &'a [u8]) -> Option>> { + pub fn parse_options_list(input: &'a [u8]) -> Option; 4]>> { parser::angle_bracket_delimeted_list(input) .map(|mut vec| { /* Prefer email options first, since this _is_ a mail client after all and it's @@ -61,20 +62,13 @@ impl<'a> ListAction<'a> { vec.into_iter() .map(|elem| ListAction::from(elem)) - .collect::>>() + .collect::; 4]>>() }) .to_full_result() .ok() } } -/* Required for StackVec's place holder elements, never actually used */ -impl<'a> Default for ListAction<'a> { - fn default() -> Self { - ListAction::Email(b"") - } -} - impl<'a> Clone for ListAction<'a> { fn clone(&self) -> Self { match self { @@ -88,8 +82,8 @@ impl<'a> Clone for ListAction<'a> { pub struct ListActions<'a> { pub id: Option<&'a str>, pub archive: Option<&'a str>, - pub post: Option>>, - pub unsubscribe: Option>>, + pub post: Option; 4]>>, + pub unsubscribe: Option; 4]>>, } pub fn list_id_header<'a>(envelope: &'a Envelope) -> Option<&'a str> { diff --git a/melib/src/lib.rs b/melib/src/lib.rs index 36cc0e72..468bfc14 100644 --- a/melib/src/lib.rs +++ b/melib/src/lib.rs @@ -123,8 +123,6 @@ pub mod mailbox; pub mod thread; pub use crate::email::*; pub use crate::thread::*; -mod structs; -pub use self::structs::*; pub mod parsec; #[macro_use] diff --git a/melib/src/structs.rs b/melib/src/structs.rs deleted file mode 100644 index f4d1b427..00000000 --- a/melib/src/structs.rs +++ /dev/null @@ -1,253 +0,0 @@ -/* - * meli - melib crate. - * - * Copyright 2019 Manos Pitsidianakis - * - * This file is part of meli. - * - * meli is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * meli is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with meli. If not, see . - */ - -use std::iter::{Extend, FromIterator}; -use std::ops::Index; -use std::ops::IndexMut; - -const STACK_VEC_CAPACITY: usize = 32; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct StackVec { - len: usize, - array: [T; STACK_VEC_CAPACITY], - heap_vec: Vec, -} - -impl StackVec { - pub fn new() -> Self { - StackVec { - len: 0, - array: [T::default(); STACK_VEC_CAPACITY], - heap_vec: Vec::new(), - } - } - pub fn push(&mut self, ind: T) { - if self.len == self.array.len() { - if self.heap_vec.is_empty() { - self.heap_vec.reserve(STACK_VEC_CAPACITY); - for _ in 0..STACK_VEC_CAPACITY { - self.heap_vec.push(T::default()); - } - } - self.heap_vec[0..STACK_VEC_CAPACITY].copy_from_slice(&self.array); - self.heap_vec.push(ind); - } else if self.len > self.array.len() { - self.heap_vec.push(ind); - } else { - self.array[self.len] = ind; - } - self.len += 1; - } - pub fn pop(&mut self) -> Option { - if self.len == 0 { - return None; - } - if self.len > self.array.len() { - self.len -= 1; - self.heap_vec.pop() - } else { - let ret = self.array[self.len - 1]; - self.len -= 1; - Some(ret) - } - } - pub fn len(&self) -> usize { - self.len - } - pub fn is_empty(&self) -> bool { - self.len == 0 - } - pub fn iter(&self) -> StackVecIter { - StackVecIter { - stack: &self, - range: 0..self.len, - } - } - pub fn remove(&mut self, i: usize) -> T { - if self.len > self.array.len() { - self.len -= 1; - self.heap_vec.remove(i) - } else { - let ret = std::mem::replace(&mut self.array[i], T::default()); - self.len -= 1; - for i in i..self.len { - self.array[i] = self.array[i + 1]; - } - ret - } - } - - pub fn set(&mut self, i: usize, val: T) { - debug_assert!(i < self.len); - if self.len > self.array.len() { - self.heap_vec[i] = val; - if i < self.array.len() { - self.array[i] = val; - } - } else { - self.array[i] = val; - } - } - - pub fn clear(&mut self) { - self.len = 0; - } -} - -pub struct StackVecIter<'a, T: Default + Copy + std::fmt::Debug> { - stack: &'a StackVec, - range: std::ops::Range, -} - -impl<'a, T: Default + Copy + std::fmt::Debug> Iterator for StackVecIter<'a, T> { - type Item = &'a T; - fn next(&mut self) -> Option<&'a T> { - if self.range.len() == 0 { - None - } else { - let idx = self.range.start; - self.range.start += 1; - Some(&self.stack[idx]) - } - } -} -impl<'a, T: Default + Copy + std::fmt::Debug> std::iter::DoubleEndedIterator - for StackVecIter<'a, T> -{ - fn next_back(&mut self) -> Option<&'a T> { - if self.range.len() == 0 { - None - } else { - let idx = self.range.end - 1; - self.range.end -= 1; - Some(&self.stack[idx]) - } - } -} - -impl Index for StackVec { - type Output = T; - - fn index(&self, idx: usize) -> &T { - if self.len > self.array.len() { - &self.heap_vec[idx] - } else { - &self.array[idx] - } - } -} - -impl IndexMut for StackVec { - fn index_mut(&mut self, idx: usize) -> &mut T { - if self.len > self.array.len() { - &mut self.heap_vec[idx] - } else { - &mut self.array[idx] - } - } -} - -impl Extend for StackVec { - fn extend(&mut self, iter: I) - where - I: IntoIterator, - { - for elem in iter { - self.push(elem); - } - } -} - -impl FromIterator for StackVec { - fn from_iter>(iter: I) -> Self { - let mut c = StackVec::new(); - - for i in iter { - c.push(i); - } - - c - } -} - -pub struct StackVecIterOwned(StackVec); -impl IntoIterator for StackVec { - type Item = T; - type IntoIter = StackVecIterOwned; - - fn into_iter(self) -> Self::IntoIter { - StackVecIterOwned(self) - } -} - -impl<'a, T: Default + Copy + std::fmt::Debug> IntoIterator for &'a StackVec { - type Item = &'a T; - type IntoIter = StackVecIter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl Iterator for StackVecIterOwned { - type Item = T; - fn next(&mut self) -> Option { - if self.0.is_empty() { - None - } else { - Some(self.0.remove(0)) - } - } -} -impl std::iter::DoubleEndedIterator for StackVecIterOwned { - fn next_back(&mut self) -> Option { - if self.0.is_empty() { - None - } else { - self.0.pop() - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_stackvec() { - let mut stack = StackVec::from_iter(0..4 * STACK_VEC_CAPACITY); - let mut ctr = 0; - assert!(stack.iter().all(|&x| { - let ret = x == ctr; - ctr += 1; - ret - })); - for _ in 0..(3 * STACK_VEC_CAPACITY) + 1 { - stack.pop(); - } - ctr = 0; - assert!(stack.iter().all(|&x| { - let ret = x == ctr; - ctr += 1; - ret - })); - } -} diff --git a/melib/src/thread.rs b/melib/src/thread.rs index 9c8fdbfe..0b3464cb 100644 --- a/melib/src/thread.rs +++ b/melib/src/thread.rs @@ -35,7 +35,6 @@ use crate::datetime::UnixTimestamp; use crate::email::parser::BytesExt; use crate::email::*; -use crate::structs::StackVec; #[cfg(feature = "unicode_algorithms")] use text_processing::grapheme_clusters::*; @@ -53,6 +52,8 @@ use std::str::FromStr; use std::string::ToString; use std::sync::{Arc, RwLock}; +use smallvec::SmallVec; + type Envelopes = Arc>>; #[derive(PartialEq, Hash, Eq, Copy, Clone, Serialize, Deserialize, Default)] @@ -279,7 +280,7 @@ impl FromStr for SortOrder { pub struct ThreadsIterator<'a> { pos: usize, - stack: StackVec, + stack: SmallVec<[usize; 16]>, root_tree: Ref<'a, Vec>, thread_nodes: &'a FnvHashMap, } @@ -332,7 +333,7 @@ impl<'a> Iterator for ThreadsIterator<'a> { pub struct ThreadIterator<'a> { init_pos: usize, pos: usize, - stack: StackVec, + stack: SmallVec<[usize; 16]>, root_tree: Ref<'a, Vec>, thread_nodes: &'a FnvHashMap, } @@ -724,7 +725,7 @@ impl Threads { pub fn threads_iter(&self) -> ThreadsIterator { ThreadsIterator { pos: 0, - stack: StackVec::new(), + stack: SmallVec::new(), root_tree: self.tree_index.borrow(), thread_nodes: &self.thread_nodes, } @@ -734,7 +735,7 @@ impl Threads { ThreadIterator { init_pos: index, pos: index, - stack: StackVec::new(), + stack: SmallVec::new(), root_tree: self.tree_index.borrow(), thread_nodes: &self.thread_nodes, } diff --git a/src/bin.rs b/src/bin.rs index b41f6825..d031c92a 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -256,7 +256,7 @@ fn run_app() -> Result<()> { 'inner: loop { /* Check if any components have sent reply events to State. */ - let events: Vec = state.context.replies(); + let events: ui::smallvec::SmallVec<[UIEvent; 8]> = state.context.replies(); for e in events { state.rcv_event(e); } diff --git a/testing/src/linebreak.rs b/testing/src/linebreak.rs index 1d3eedf0..ec93603c 100644 --- a/testing/src/linebreak.rs +++ b/testing/src/linebreak.rs @@ -1,6 +1,5 @@ extern crate melib; use melib::Result; -use melib::StackVec; extern crate text_processing; use text_processing::line_break::*; @@ -14,14 +13,14 @@ fn cost(i: usize, j: usize, width: usize, minima: &Vec, offsets: &Vec, - columns: &mut StackVec, + rows: &mut Vec, + columns: &mut Vec, minima: &mut Vec, breaks: &mut Vec, width: usize, offsets: &Vec, ) { - let mut stack = StackVec::new(); + let mut stack = Vec::new(); let mut i = 0; while i < rows.len() { if stack.len() > 0 { @@ -46,7 +45,7 @@ fn smawk( let mut odd_columns = columns.iter().skip(1).step_by(2).cloned().collect(); smawk(rows, &mut odd_columns, minima, breaks, width, offsets); for (i, o) in odd_columns.into_iter().enumerate() { - columns.set(2 * i + 1, o); + columns[2 * i + 1] = o; } } let mut i = 0; diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 020ea1ab..41de817a 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -30,6 +30,7 @@ rusqlite = {version = "0.20.0", optional =true } rmp = "^0.8" rmpv = { version = "^0.4.2", features=["with-serde",] } rmp-serde = "^0.14.0" +smallvec = { version = "1.1.0", features = ["serde", ] } [features] default = ["sqlite3"] diff --git a/ui/src/cache.rs b/ui/src/cache.rs index afb542e1..29f187b8 100644 --- a/ui/src/cache.rs +++ b/ui/src/cache.rs @@ -25,7 +25,7 @@ use melib::{ backends::{FolderHash, MailBackend}, email::EnvelopeHash, thread::{SortField, SortOrder}, - Result, StackVec, + Result, }; use std::sync::{Arc, RwLock}; @@ -429,7 +429,7 @@ pub fn imap_search( (_sort_field, _sort_order): (SortField, SortOrder), folder_hash: FolderHash, backend: &Arc>>, -) -> Result> { +) -> Result> { let query = query().parse(term)?.1; let backend_lck = backend.read().unwrap(); diff --git a/ui/src/components/mail/listing.rs b/ui/src/components/mail/listing.rs index 1157e03c..69a93e8b 100644 --- a/ui/src/components/mail/listing.rs +++ b/ui/src/components/mail/listing.rs @@ -21,6 +21,7 @@ use super::*; use crate::types::segment_tree::SegmentTree; +use smallvec::SmallVec; mod conversations; pub use self::conversations::*; @@ -56,10 +57,10 @@ pub trait MailListingTrait: ListingTrait { a: &ListingAction, ) { let account = &mut context.accounts[self.coordinates().0]; - let mut envs_to_set: StackVec = StackVec::new(); + let mut envs_to_set: SmallVec<[EnvelopeHash; 8]> = SmallVec::new(); let folder_hash = account[self.coordinates().1].unwrap().folder.hash(); { - let mut stack = StackVec::new(); + let mut stack: SmallVec<[ThreadHash; 8]> = SmallVec::new(); stack.push(thread_hash); while let Some(thread_iter) = stack.pop() { { @@ -138,8 +139,8 @@ pub trait MailListingTrait: ListingTrait { } } - fn row_updates(&mut self) -> &mut StackVec; - fn get_focused_items(&self, _context: &Context) -> StackVec; + fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]>; + fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]>; } pub trait ListingTrait: Component { diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index 0d4df95a..47f81d01 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -69,18 +69,18 @@ pub struct CompactListing { /// If `self.view` exists or not. unfocused: bool, view: ThreadView, - row_updates: StackVec, + row_updates: SmallVec<[ThreadHash; 8]>, movement: Option, id: ComponentId, } impl MailListingTrait for CompactListing { - fn row_updates(&mut self) -> &mut StackVec { + fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> { &mut self.row_updates } - fn get_focused_items(&self, context: &Context) -> StackVec { + fn get_focused_items(&self, context: &Context) -> SmallVec<[ThreadHash; 8]> { let is_selection_empty = self.selection.values().cloned().any(std::convert::identity); let i = [self.get_thread_under_cursor(self.cursor_pos.2, context)]; let cursor_iter; @@ -96,7 +96,7 @@ impl MailListingTrait for CompactListing { .flatten() .chain(cursor_iter.into_iter().flatten()) .cloned(); - StackVec::from_iter(iter.into_iter()) + SmallVec::from_iter(iter.into_iter()) } } @@ -530,7 +530,7 @@ impl CompactListing { filtered_selection: Vec::new(), filtered_order: FnvHashMap::default(), selection: FnvHashMap::default(), - row_updates: StackVec::new(), + row_updates: SmallVec::new(), data_columns: DataColumns::default(), dirty: true, force_draw: true, @@ -554,7 +554,7 @@ impl CompactListing { .hash(); let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash]; let mut tags = String::new(); - let mut colors = StackVec::new(); + let mut colors: SmallVec<[_; 8]> = SmallVec::new(); let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap(); if let Some(t) = backend_lck.tags() { let tags_lck = t.read().unwrap(); @@ -681,17 +681,17 @@ impl CompactListing { let mut rows = Vec::with_capacity(1024); let mut min_width = (0, 0, 0, 0, 0); let mut row_widths: ( - StackVec, - StackVec, - StackVec, - StackVec, - StackVec, + SmallVec<[u8; 1024]>, + SmallVec<[u8; 1024]>, + SmallVec<[u8; 1024]>, + SmallVec<[u8; 1024]>, + SmallVec<[u8; 1024]>, ) = ( - StackVec::new(), - StackVec::new(), - StackVec::new(), - StackVec::new(), - StackVec::new(), + SmallVec::new(), + SmallVec::new(), + SmallVec::new(), + SmallVec::new(), + SmallVec::new(), ); threads.sort_by(self.sort, self.subsort, &account.collection.envelopes); diff --git a/ui/src/components/mail/listing/conversations.rs b/ui/src/components/mail/listing/conversations.rs index 3b72cdc4..3b322706 100644 --- a/ui/src/components/mail/listing/conversations.rs +++ b/ui/src/components/mail/listing/conversations.rs @@ -73,7 +73,7 @@ column_str!(struct DateString(String)); column_str!(struct FromString(String)); column_str!(struct SubjectString(String)); column_str!(struct FlagString(String)); -column_str!(struct TagString(String, StackVec)); +column_str!(struct TagString(String, SmallVec<[Color; 8]>)); /// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a /// `ThreadView`. @@ -100,18 +100,18 @@ pub struct ConversationsListing { /// If `self.view` exists or not. unfocused: bool, view: ThreadView, - row_updates: StackVec, + row_updates: SmallVec<[ThreadHash; 8]>, movement: Option, id: ComponentId, } impl MailListingTrait for ConversationsListing { - fn row_updates(&mut self) -> &mut StackVec { + fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> { &mut self.row_updates } - fn get_focused_items(&self, context: &Context) -> StackVec { + fn get_focused_items(&self, context: &Context) -> SmallVec<[ThreadHash; 8]> { let is_selection_empty = self.selection.values().cloned().any(std::convert::identity); let i = [self.get_thread_under_cursor(self.cursor_pos.2, context)]; let cursor_iter; @@ -127,7 +127,7 @@ impl MailListingTrait for ConversationsListing { .flatten() .chain(cursor_iter.into_iter().flatten()) .cloned(); - StackVec::from_iter(iter.into_iter()) + SmallVec::from_iter(iter.into_iter()) } } @@ -500,7 +500,7 @@ impl ConversationsListing { filtered_selection: Vec::new(), filtered_order: FnvHashMap::default(), selection: FnvHashMap::default(), - row_updates: StackVec::new(), + row_updates: SmallVec::new(), content: Default::default(), dirty: true, force_draw: true, @@ -525,7 +525,7 @@ impl ConversationsListing { .hash(); let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash]; let mut tags = String::new(); - let mut colors = StackVec::new(); + let mut colors = SmallVec::new(); let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap(); if let Some(t) = backend_lck.tags() { let tags_lck = t.read().unwrap(); @@ -690,7 +690,7 @@ impl ConversationsListing { } from_address_list.clear(); from_address_set.clear(); - let mut stack = StackVec::new(); + let mut stack: SmallVec<[ThreadHash; 8]> = SmallVec::new(); stack.push(root_idx); while let Some(h) = stack.pop() { let env_hash = if let Some(h) = threads.thread_nodes()[&h].message() { @@ -952,7 +952,7 @@ impl ConversationsListing { let mut from_address_list = Vec::new(); let mut from_address_set: std::collections::HashSet> = std::collections::HashSet::new(); - let mut stack = StackVec::new(); + let mut stack: SmallVec<[ThreadHash; 8]> = SmallVec::new(); stack.push(thread_hash); while let Some(h) = stack.pop() { let env_hash = if let Some(h) = threads.thread_nodes()[&h].message() { diff --git a/ui/src/components/mail/listing/plain.rs b/ui/src/components/mail/listing/plain.rs index b1f8de8c..c2410416 100644 --- a/ui/src/components/mail/listing/plain.rs +++ b/ui/src/components/mail/listing/plain.rs @@ -70,19 +70,19 @@ pub struct PlainListing { /// If `self.view` exists or not. unfocused: bool, view: MailView, - row_updates: StackVec, - _row_updates: StackVec, + row_updates: SmallVec<[EnvelopeHash; 8]>, + _row_updates: SmallVec<[ThreadHash; 8]>, movement: Option, id: ComponentId, } impl MailListingTrait for PlainListing { - fn row_updates(&mut self) -> &mut StackVec { + fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> { &mut self._row_updates } - fn get_focused_items(&self, context: &Context) -> StackVec { + fn get_focused_items(&self, context: &Context) -> SmallVec<[ThreadHash; 8]> { let is_selection_empty = self.selection.values().cloned().any(std::convert::identity); if is_selection_empty { self.selection @@ -91,7 +91,7 @@ impl MailListingTrait for PlainListing { .map(|(k, _)| self.thread_hashes[k]) .collect() } else { - let mut ret = StackVec::new(); + let mut ret = SmallVec::new(); ret.push(self.get_thread_under_cursor(self.cursor_pos.2, context)); ret } @@ -484,8 +484,8 @@ impl PlainListing { filtered_selection: Vec::new(), filtered_order: FnvHashMap::default(), selection: FnvHashMap::default(), - row_updates: StackVec::new(), - _row_updates: StackVec::new(), + row_updates: SmallVec::new(), + _row_updates: SmallVec::new(), data_columns: DataColumns::default(), dirty: true, force_draw: true, @@ -503,7 +503,7 @@ impl PlainListing { .hash(); let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash]; let mut tags = String::new(); - let mut colors = StackVec::new(); + let mut colors = SmallVec::new(); let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap(); if let Some(t) = backend_lck.tags() { let tags_lck = t.read().unwrap(); @@ -1086,7 +1086,7 @@ impl Component for PlainListing { .flatten() .chain(cursor_iter.into_iter().flatten()) .cloned(); - let stack = StackVec::from_iter(iter.into_iter()); + let stack: SmallVec<[_; 8]> = SmallVec::from_iter(iter.into_iter()); for i in stack { self.perform_action(context, i, a); } diff --git a/ui/src/components/mail/listing/thread.rs b/ui/src/components/mail/listing/thread.rs index eb25a2ec..6a81a735 100644 --- a/ui/src/components/mail/listing/thread.rs +++ b/ui/src/components/mail/listing/thread.rs @@ -37,7 +37,7 @@ pub struct ThreadListing { /// Cache current view. content: CellBuffer, - row_updates: StackVec, + row_updates: SmallVec<[ThreadHash; 8]>, locations: Vec, /// If we must redraw on next redraw event dirty: bool, @@ -50,12 +50,12 @@ pub struct ThreadListing { } impl MailListingTrait for ThreadListing { - fn row_updates(&mut self) -> &mut StackVec { + fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> { &mut self.row_updates } - fn get_focused_items(&self, _context: &Context) -> StackVec { - StackVec::new() + fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> { + SmallVec::new() } } @@ -242,7 +242,7 @@ impl ThreadListing { sort: (Default::default(), Default::default()), subsort: (Default::default(), Default::default()), content, - row_updates: StackVec::new(), + row_updates: SmallVec::new(), locations: Vec::new(), dirty: true, unfocused: false, diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs index 7fcf78b4..630be357 100644 --- a/ui/src/components/mail/view.rs +++ b/ui/src/components/mail/view.rs @@ -22,6 +22,7 @@ use super::*; use melib::list_management; use melib::parser::BytesExt; +use smallvec::SmallVec; use std::convert::TryFrom; use std::process::{Command, Stdio}; @@ -229,7 +230,7 @@ impl MailView { if body.count_attachments() > 1 { fn attachment_tree( (idx, (depth, att)): (&mut usize, (usize, &Attachment)), - branches: &mut StackVec, + branches: &mut SmallVec<[bool; 8]>, has_sibling: bool, s: &mut String, ) { @@ -286,7 +287,7 @@ impl MailView { _ => {} } } - attachment_tree((&mut 0, (0, &body)), &mut StackVec::new(), false, &mut t); + attachment_tree((&mut 0, (0, &body)), &mut SmallVec::new(), false, &mut t); } t } @@ -1385,7 +1386,7 @@ impl Component for MailView { } _ => { /* error print message to user */ } } - } + }; } UIEvent::Action(Listing(OpenInNewTab)) => { context diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs index 9cdb3110..5964e356 100644 --- a/ui/src/components/mail/view/thread.rs +++ b/ui/src/components/mail/view/thread.rs @@ -848,7 +848,7 @@ impl ThreadView { .iter() .enumerate() .fold( - (vec![Vec::new()], StackVec::new(), false), + (vec![Vec::new()], SmallVec::<[_; 8]>::new(), false), |(mut visies, mut stack, is_prev_hidden), (idx, e)| { match (e.hidden, is_prev_hidden) { (true, false) => { diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index 6239cdd5..c4c6ac7c 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -34,7 +34,7 @@ use melib::error::{MeliError, Result}; use melib::mailbox::*; use melib::thread::{SortField, SortOrder, ThreadHash, ThreadNode, Threads}; use melib::AddressBook; -use melib::StackVec; +use smallvec::SmallVec; use text_processing::GlobMatch; use crate::types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification}; @@ -384,7 +384,7 @@ impl Account { folder_names.insert(f.hash(), f.path().to_string()); } - let mut stack: StackVec = StackVec::new(); + let mut stack: SmallVec<[FolderHash; 8]> = SmallVec::new(); let mut tree: Vec = Vec::new(); let mut collection: Collection = Collection::new(Default::default()); for (h, f) in ref_folders.iter() { @@ -442,7 +442,7 @@ impl Account { } }); - let mut stack: StackVec> = StackVec::new(); + let mut stack: SmallVec<[Option<&FolderNode>; 8]> = SmallVec::new(); for n in tree.iter_mut() { folders_order.push(n.hash); n.kids.sort_unstable_by(|a, b| { @@ -462,6 +462,7 @@ impl Account { stack.extend(next.kids.iter().rev().map(Some)); } } + drop(stack); self.folders = folders; self.ref_folders = ref_folders; @@ -1053,7 +1054,7 @@ impl Account { search_term: &str, sort: (SortField, SortOrder), folder_hash: FolderHash, - ) -> Result> { + ) -> Result> { if self.settings.account().format() == "imap" { return crate::cache::imap_search(search_term, sort, folder_hash, &self.backend); } @@ -1081,7 +1082,7 @@ impl Account { #[cfg(not(feature = "sqlite3"))] { - let mut ret = StackVec::new(); + let mut ret = SmallVec::new(); let envelopes = self.collection.envelopes.clone().read(); let envelopes = envelopes.unwrap(); diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 8b109388..3fbc37c8 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -40,6 +40,7 @@ extern crate termion; extern crate nom; extern crate serde_json; +pub extern crate smallvec; use melib::*; use std::collections::VecDeque; diff --git a/ui/src/sqlite3.rs b/ui/src/sqlite3.rs index 526c4c51..c001236d 100644 --- a/ui/src/sqlite3.rs +++ b/ui/src/sqlite3.rs @@ -19,6 +19,7 @@ * along with meli. If not, see . */ +use smallvec::SmallVec; use crate::cache::query; use crate::cache::Query::{self, *}; use crate::melib::parsec::Parser; @@ -27,7 +28,7 @@ use melib::{ email::{Envelope, EnvelopeHash}, log, thread::{SortField, SortOrder}, - MeliError, Result, StackVec, ERROR, + MeliError, Result, ERROR, }; use rusqlite::{params, Connection}; use std::borrow::Cow; @@ -389,7 +390,7 @@ pub fn index(context: &mut crate::state::Context, account_name: &str) -> Result< pub fn search( term: &str, (sort_field, sort_order): (SortField, SortOrder), -) -> Result> { +) -> Result> { let conn = open_db()?; let sort_field = match debug!(sort_field) { @@ -425,7 +426,7 @@ pub fn search( .map_err(|e: std::array::TryFromSliceError| MeliError::new(e.to_string()))?, )) }) - .collect::>>(); + .collect::>>(); results } diff --git a/ui/src/state.rs b/ui/src/state.rs index af3d8e9a..360f08eb 100644 --- a/ui/src/state.rs +++ b/ui/src/state.rs @@ -103,7 +103,7 @@ pub struct Context { } impl Context { - pub fn replies(&mut self) -> Vec { + pub fn replies(&mut self) -> smallvec::SmallVec<[UIEvent; 8]> { self.replies.drain(0..).collect() } @@ -437,7 +437,8 @@ impl State { for i in 0..self.components.len() { self.draw_component(i); } - let mut areas: Vec = self.context.dirty_areas.drain(0..).collect(); + let mut areas: smallvec::SmallVec<[Area; 8]> = + self.context.dirty_areas.drain(0..).collect(); if areas.is_empty() { return; } @@ -682,7 +683,8 @@ impl State { } if !self.context.replies.is_empty() { - let replies: Vec = self.context.replies.drain(0..).collect(); + let replies: smallvec::SmallVec<[UIEvent; 8]> = + self.context.replies.drain(0..).collect(); // Pass replies to self and call count on the map iterator to force evaluation replies.into_iter().map(|r| self.rcv_event(r)).count(); } diff --git a/ui/src/types.rs b/ui/src/types.rs index fa88c07c..166b17e1 100644 --- a/ui/src/types.rs +++ b/ui/src/types.rs @@ -152,24 +152,24 @@ pub mod segment_tree { /*! Simple segment tree implementation for maximum in range queries. This is useful if given an * array of numbers you want to get the maximum value inside an interval quickly. */ - use melib::StackVec; + use smallvec::SmallVec; use std::convert::TryFrom; use std::iter::FromIterator; #[derive(Default, Debug, Clone)] pub struct SegmentTree { - array: StackVec, - tree: StackVec, + array: SmallVec<[u8; 1024]>, + tree: SmallVec<[u8; 1024]>, } - impl From> for SegmentTree { - fn from(val: StackVec) -> SegmentTree { + impl From> for SegmentTree { + fn from(val: SmallVec<[u8; 1024]>) -> SegmentTree { SegmentTree::new(val) } } impl SegmentTree { - pub fn new(val: StackVec) -> SegmentTree { + pub fn new(val: SmallVec<[u8; 1024]>) -> SegmentTree { if val.is_empty() { return SegmentTree { array: val.clone(), @@ -182,8 +182,8 @@ pub mod segment_tree { .ceil() as u32; let max_size = 2 * (2_usize.pow(height)) - 1; - let mut segment_tree: StackVec = - StackVec::from_iter(core::iter::repeat(0).take(max_size)); + let mut segment_tree: SmallVec<[u8; 1024]> = + SmallVec::from_iter(core::iter::repeat(0).take(max_size)); for i in 0..val.len() { segment_tree[val.len() + i] = val[i]; } @@ -231,10 +231,10 @@ pub mod segment_tree { #[test] fn test_segment_tree() { - let array: StackVec = [9, 1, 17, 2, 3, 23, 4, 5, 6, 37] + let array: SmallVec<[u8; 1024]> = [9, 1, 17, 2, 3, 23, 4, 5, 6, 37] .into_iter() .cloned() - .collect::>(); + .collect::>(); let segment_tree = SegmentTree::from(array.clone()); assert_eq!(segment_tree.get_max(0, 5), 23);