Replace StackVec with smallvec::SmallVec
SmallVec has a less buggy and better implementation.memfd
parent
b6403f486b
commit
a365a846b8
|
@ -771,6 +771,7 @@ dependencies = [
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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_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)",
|
"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)",
|
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"text_processing 0.4.1",
|
"text_processing 0.4.1",
|
||||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1553,8 +1554,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "sourcefile"
|
name = "sourcefile"
|
||||||
|
@ -1860,6 +1864,7 @@ dependencies = [
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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_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)",
|
"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)",
|
"termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"text_processing 0.4.1",
|
"text_processing 0.4.1",
|
||||||
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1889,7 +1894,7 @@ name = "unicode-normalization"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[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 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 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 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 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 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"
|
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
||||||
|
|
|
@ -27,6 +27,7 @@ text_processing = { path = "../text_processing", version = "*", optional= true }
|
||||||
libc = {version = "0.2.59", features = ["extra_traits",]}
|
libc = {version = "0.2.59", features = ["extra_traits",]}
|
||||||
reqwest = { version ="0.10.0-alpha.2", optional=true, features = ["json", "blocking" ]}
|
reqwest = { version ="0.10.0-alpha.2", optional=true, features = ["json", "blocking" ]}
|
||||||
serde_json = { version = "1.0", optional = true, features = ["raw_value",] }
|
serde_json = { version = "1.0", optional = true, features = ["raw_value",] }
|
||||||
|
smallvec = { version = "1.1.0", features = ["serde", ] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["unicode_algorithms", "imap_backend", "maildir_backend", "mbox_backend", "vcard"]
|
default = ["unicode_algorithms", "imap_backend", "maildir_backend", "mbox_backend", "vcard"]
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use smallvec::SmallVec;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod protocol_parser;
|
mod protocol_parser;
|
||||||
pub use protocol_parser::{UntaggedResponse::*, *};
|
pub use protocol_parser::{UntaggedResponse::*, *};
|
||||||
|
@ -677,7 +678,7 @@ impl ImapType {
|
||||||
&self,
|
&self,
|
||||||
query: String,
|
query: String,
|
||||||
folder_hash: FolderHash,
|
folder_hash: FolderHash,
|
||||||
) -> Result<crate::structs::StackVec<EnvelopeHash>> {
|
) -> Result<SmallVec<[EnvelopeHash; 512]>> {
|
||||||
let folders_lck = self.folders.read()?;
|
let folders_lck = self.folders.read()?;
|
||||||
let mut response = String::with_capacity(8 * 1024);
|
let mut response = String::with_capacity(8 * 1024);
|
||||||
let mut conn = self.connection.lock()?;
|
let mut conn = self.connection.lock()?;
|
||||||
|
@ -692,7 +693,7 @@ impl ImapType {
|
||||||
if l.starts_with("* SEARCH") {
|
if l.starts_with("* SEARCH") {
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
let uid_index = self.uid_store.uid_index.lock()?;
|
let uid_index = self.uid_store.uid_index.lock()?;
|
||||||
return Ok(crate::structs::StackVec::from_iter(
|
return Ok(SmallVec::from_iter(
|
||||||
l["* SEARCH".len()..]
|
l["* SEARCH".len()..]
|
||||||
.trim()
|
.trim()
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
|
|
||||||
use super::folder::JmapFolder;
|
use super::folder::JmapFolder;
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::structs::StackVec;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
@ -327,10 +327,10 @@ pub fn get(
|
||||||
}
|
}
|
||||||
tag_hash
|
tag_hash
|
||||||
})
|
})
|
||||||
.collect::<StackVec<u64>>();
|
.collect::<SmallVec<[u64; 1024]>>();
|
||||||
(tags, obj.id.clone(), obj.blob_id.clone())
|
(tags, obj.id.clone(), obj.blob_id.clone())
|
||||||
})
|
})
|
||||||
.collect::<Vec<(StackVec<u64>, Id, Id)>>();
|
.collect::<Vec<(SmallVec<[u64; 1024]>, Id, Id)>>();
|
||||||
drop(tag_lck);
|
drop(tag_lck);
|
||||||
let mut ret = list
|
let mut ret = list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
use crate::async_workers::{Async, AsyncBuilder, AsyncStatus, WorkContext};
|
||||||
use crate::backends::FolderHash;
|
use crate::backends::FolderHash;
|
||||||
use crate::backends::{
|
use crate::backends::{
|
||||||
|
@ -8,8 +29,8 @@ use crate::conf::AccountSettings;
|
||||||
use crate::email::{Envelope, EnvelopeHash, Flag};
|
use crate::email::{Envelope, EnvelopeHash, Flag};
|
||||||
use crate::error::{MeliError, Result};
|
use crate::error::{MeliError, Result};
|
||||||
use crate::shellexpand::ShellExpandTrait;
|
use crate::shellexpand::ShellExpandTrait;
|
||||||
use crate::structs::StackVec;
|
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
@ -229,7 +250,7 @@ impl NotmuchDb {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search(&self, query_s: &str) -> Result<crate::structs::StackVec<EnvelopeHash>> {
|
pub fn search(&self, query_s: &str) -> Result<SmallVec<[EnvelopeHash; 512]>> {
|
||||||
let database_lck = self.database.inner.read().unwrap();
|
let database_lck = self.database.inner.read().unwrap();
|
||||||
let query_str = std::ffi::CString::new(query_s).unwrap();
|
let query_str = std::ffi::CString::new(query_s).unwrap();
|
||||||
let query: *mut notmuch_query_t =
|
let query: *mut notmuch_query_t =
|
||||||
|
@ -247,7 +268,7 @@ impl NotmuchDb {
|
||||||
}
|
}
|
||||||
assert!(!messages.is_null());
|
assert!(!messages.is_null());
|
||||||
let iter = MessageIterator { messages };
|
let iter = MessageIterator { messages };
|
||||||
let mut ret = StackVec::new();
|
let mut ret = SmallVec::new();
|
||||||
for message in iter {
|
for message in iter {
|
||||||
let fs_path = unsafe { notmuch_message_get_filename(message) };
|
let fs_path = unsafe { notmuch_message_get_filename(message) };
|
||||||
let c_str = unsafe { CStr::from_ptr(fs_path) };
|
let c_str = unsafe { CStr::from_ptr(fs_path) };
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::backends::FolderHash;
|
use crate::backends::FolderHash;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
@ -160,7 +161,7 @@ impl Collection {
|
||||||
mut new_envelopes: FnvHashMap<EnvelopeHash, Envelope>,
|
mut new_envelopes: FnvHashMap<EnvelopeHash, Envelope>,
|
||||||
folder_hash: FolderHash,
|
folder_hash: FolderHash,
|
||||||
sent_folder: Option<FolderHash>,
|
sent_folder: Option<FolderHash>,
|
||||||
) -> Option<StackVec<FolderHash>> {
|
) -> Option<SmallVec<[FolderHash; 8]>> {
|
||||||
self.sent_folder = sent_folder;
|
self.sent_folder = sent_folder;
|
||||||
for (h, e) in new_envelopes.iter() {
|
for (h, e) in new_envelopes.iter() {
|
||||||
self.message_ids.insert(e.message_id().raw().to_vec(), *h);
|
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::<Vec<FolderHash>>();
|
let keys = threads.keys().cloned().collect::<Vec<FolderHash>>();
|
||||||
for t_fh in keys {
|
for t_fh in keys {
|
||||||
if t_fh == folder_hash {
|
if t_fh == folder_hash {
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn timestamp_to_string(timestamp: UnixTimestamp, fmt: Option<&str>) -> Strin
|
||||||
};
|
};
|
||||||
let s: CString;
|
let s: CString;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut vec: Vec<u8> = vec![0; 256];
|
let mut vec: [u8; 256] = [0; 256];
|
||||||
let ret = strftime(
|
let ret = strftime(
|
||||||
vec.as_mut_ptr() as *mut _,
|
vec.as_mut_ptr() as *mut _,
|
||||||
256,
|
256,
|
||||||
|
|
|
@ -43,6 +43,7 @@ use crate::datetime::UnixTimestamp;
|
||||||
use crate::error::{MeliError, Result};
|
use crate::error::{MeliError, Result};
|
||||||
use crate::thread::ThreadHash;
|
use crate::thread::ThreadHash;
|
||||||
|
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
@ -132,7 +133,7 @@ pub struct Envelope {
|
||||||
|
|
||||||
flags: Flag,
|
flags: Flag,
|
||||||
has_attachments: bool,
|
has_attachments: bool,
|
||||||
labels: crate::structs::StackVec<u64>,
|
labels: SmallVec<[u64; 8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Envelope {
|
impl fmt::Debug for Envelope {
|
||||||
|
@ -170,7 +171,7 @@ impl Envelope {
|
||||||
hash,
|
hash,
|
||||||
has_attachments: false,
|
has_attachments: false,
|
||||||
flags: Flag::default(),
|
flags: Flag::default(),
|
||||||
labels: crate::structs::StackVec::new(),
|
labels: SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,11 +610,11 @@ impl Envelope {
|
||||||
self.has_attachments
|
self.has_attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn labels(&self) -> &crate::structs::StackVec<u64> {
|
pub fn labels(&self) -> &SmallVec<[u64; 8]> {
|
||||||
&self.labels
|
&self.labels
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn labels_mut(&mut self) -> &mut crate::structs::StackVec<u64> {
|
pub fn labels_mut(&mut self) -> &mut SmallVec<[u64; 8]> {
|
||||||
&mut self.labels
|
&mut self.labels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,10 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::parser;
|
use super::parser;
|
||||||
use super::Envelope;
|
use super::Envelope;
|
||||||
use crate::StackVec;
|
use smallvec::SmallVec;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
|
||||||
#[derive(Debug, Copy)]
|
#[derive(Debug, Copy)]
|
||||||
|
@ -46,7 +47,7 @@ impl<'a> From<&'a [u8]> for ListAction<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ListAction<'a> {
|
impl<'a> ListAction<'a> {
|
||||||
pub fn parse_options_list(input: &'a [u8]) -> Option<StackVec<ListAction<'a>>> {
|
pub fn parse_options_list(input: &'a [u8]) -> Option<SmallVec<[ListAction<'a>; 4]>> {
|
||||||
parser::angle_bracket_delimeted_list(input)
|
parser::angle_bracket_delimeted_list(input)
|
||||||
.map(|mut vec| {
|
.map(|mut vec| {
|
||||||
/* Prefer email options first, since this _is_ a mail client after all and it's
|
/* 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()
|
vec.into_iter()
|
||||||
.map(|elem| ListAction::from(elem))
|
.map(|elem| ListAction::from(elem))
|
||||||
.collect::<StackVec<ListAction<'a>>>()
|
.collect::<SmallVec<[ListAction<'a>; 4]>>()
|
||||||
})
|
})
|
||||||
.to_full_result()
|
.to_full_result()
|
||||||
.ok()
|
.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> {
|
impl<'a> Clone for ListAction<'a> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
|
@ -88,8 +82,8 @@ impl<'a> Clone for ListAction<'a> {
|
||||||
pub struct ListActions<'a> {
|
pub struct ListActions<'a> {
|
||||||
pub id: Option<&'a str>,
|
pub id: Option<&'a str>,
|
||||||
pub archive: Option<&'a str>,
|
pub archive: Option<&'a str>,
|
||||||
pub post: Option<StackVec<ListAction<'a>>>,
|
pub post: Option<SmallVec<[ListAction<'a>; 4]>>,
|
||||||
pub unsubscribe: Option<StackVec<ListAction<'a>>>,
|
pub unsubscribe: Option<SmallVec<[ListAction<'a>; 4]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_id_header<'a>(envelope: &'a Envelope) -> Option<&'a str> {
|
pub fn list_id_header<'a>(envelope: &'a Envelope) -> Option<&'a str> {
|
||||||
|
|
|
@ -123,8 +123,6 @@ pub mod mailbox;
|
||||||
pub mod thread;
|
pub mod thread;
|
||||||
pub use crate::email::*;
|
pub use crate::email::*;
|
||||||
pub use crate::thread::*;
|
pub use crate::thread::*;
|
||||||
mod structs;
|
|
||||||
pub use self::structs::*;
|
|
||||||
pub mod parsec;
|
pub mod parsec;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<T: Default + Copy + std::fmt::Debug> {
|
|
||||||
len: usize,
|
|
||||||
array: [T; STACK_VEC_CAPACITY],
|
|
||||||
heap_vec: Vec<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + Copy + std::fmt::Debug> StackVec<T> {
|
|
||||||
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<T> {
|
|
||||||
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<T> {
|
|
||||||
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<T>,
|
|
||||||
range: std::ops::Range<usize>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<T: Default + Copy + std::fmt::Debug> Index<usize> for StackVec<T> {
|
|
||||||
type Output = T;
|
|
||||||
|
|
||||||
fn index(&self, idx: usize) -> &T {
|
|
||||||
if self.len > self.array.len() {
|
|
||||||
&self.heap_vec[idx]
|
|
||||||
} else {
|
|
||||||
&self.array[idx]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + Copy + std::fmt::Debug> IndexMut<usize> for StackVec<T> {
|
|
||||||
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<T: Default + Copy + std::fmt::Debug> Extend<T> for StackVec<T> {
|
|
||||||
fn extend<I>(&mut self, iter: I)
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = T>,
|
|
||||||
{
|
|
||||||
for elem in iter {
|
|
||||||
self.push(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + Copy + std::fmt::Debug> FromIterator<T> for StackVec<T> {
|
|
||||||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
|
||||||
let mut c = StackVec::new();
|
|
||||||
|
|
||||||
for i in iter {
|
|
||||||
c.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct StackVecIterOwned<T: Default + Copy + std::fmt::Debug>(StackVec<T>);
|
|
||||||
impl<T: Default + Copy + std::fmt::Debug> IntoIterator for StackVec<T> {
|
|
||||||
type Item = T;
|
|
||||||
type IntoIter = StackVecIterOwned<T>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
StackVecIterOwned(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: Default + Copy + std::fmt::Debug> IntoIterator for &'a StackVec<T> {
|
|
||||||
type Item = &'a T;
|
|
||||||
type IntoIter = StackVecIter<'a, T>;
|
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default + Copy + std::fmt::Debug> Iterator for StackVecIterOwned<T> {
|
|
||||||
type Item = T;
|
|
||||||
fn next(&mut self) -> Option<T> {
|
|
||||||
if self.0.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.0.remove(0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: Default + Copy + std::fmt::Debug> std::iter::DoubleEndedIterator for StackVecIterOwned<T> {
|
|
||||||
fn next_back(&mut self) -> Option<T> {
|
|
||||||
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
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -35,7 +35,6 @@
|
||||||
use crate::datetime::UnixTimestamp;
|
use crate::datetime::UnixTimestamp;
|
||||||
use crate::email::parser::BytesExt;
|
use crate::email::parser::BytesExt;
|
||||||
use crate::email::*;
|
use crate::email::*;
|
||||||
use crate::structs::StackVec;
|
|
||||||
|
|
||||||
#[cfg(feature = "unicode_algorithms")]
|
#[cfg(feature = "unicode_algorithms")]
|
||||||
use text_processing::grapheme_clusters::*;
|
use text_processing::grapheme_clusters::*;
|
||||||
|
@ -53,6 +52,8 @@ use std::str::FromStr;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
type Envelopes = Arc<RwLock<FnvHashMap<EnvelopeHash, Envelope>>>;
|
type Envelopes = Arc<RwLock<FnvHashMap<EnvelopeHash, Envelope>>>;
|
||||||
|
|
||||||
#[derive(PartialEq, Hash, Eq, Copy, Clone, Serialize, Deserialize, Default)]
|
#[derive(PartialEq, Hash, Eq, Copy, Clone, Serialize, Deserialize, Default)]
|
||||||
|
@ -279,7 +280,7 @@ impl FromStr for SortOrder {
|
||||||
|
|
||||||
pub struct ThreadsIterator<'a> {
|
pub struct ThreadsIterator<'a> {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
stack: StackVec<usize>,
|
stack: SmallVec<[usize; 16]>,
|
||||||
root_tree: Ref<'a, Vec<ThreadHash>>,
|
root_tree: Ref<'a, Vec<ThreadHash>>,
|
||||||
thread_nodes: &'a FnvHashMap<ThreadHash, ThreadNode>,
|
thread_nodes: &'a FnvHashMap<ThreadHash, ThreadNode>,
|
||||||
}
|
}
|
||||||
|
@ -332,7 +333,7 @@ impl<'a> Iterator for ThreadsIterator<'a> {
|
||||||
pub struct ThreadIterator<'a> {
|
pub struct ThreadIterator<'a> {
|
||||||
init_pos: usize,
|
init_pos: usize,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
stack: StackVec<usize>,
|
stack: SmallVec<[usize; 16]>,
|
||||||
root_tree: Ref<'a, Vec<ThreadHash>>,
|
root_tree: Ref<'a, Vec<ThreadHash>>,
|
||||||
thread_nodes: &'a FnvHashMap<ThreadHash, ThreadNode>,
|
thread_nodes: &'a FnvHashMap<ThreadHash, ThreadNode>,
|
||||||
}
|
}
|
||||||
|
@ -724,7 +725,7 @@ impl Threads {
|
||||||
pub fn threads_iter(&self) -> ThreadsIterator {
|
pub fn threads_iter(&self) -> ThreadsIterator {
|
||||||
ThreadsIterator {
|
ThreadsIterator {
|
||||||
pos: 0,
|
pos: 0,
|
||||||
stack: StackVec::new(),
|
stack: SmallVec::new(),
|
||||||
root_tree: self.tree_index.borrow(),
|
root_tree: self.tree_index.borrow(),
|
||||||
thread_nodes: &self.thread_nodes,
|
thread_nodes: &self.thread_nodes,
|
||||||
}
|
}
|
||||||
|
@ -734,7 +735,7 @@ impl Threads {
|
||||||
ThreadIterator {
|
ThreadIterator {
|
||||||
init_pos: index,
|
init_pos: index,
|
||||||
pos: index,
|
pos: index,
|
||||||
stack: StackVec::new(),
|
stack: SmallVec::new(),
|
||||||
root_tree: self.tree_index.borrow(),
|
root_tree: self.tree_index.borrow(),
|
||||||
thread_nodes: &self.thread_nodes,
|
thread_nodes: &self.thread_nodes,
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ fn run_app() -> Result<()> {
|
||||||
|
|
||||||
'inner: loop {
|
'inner: loop {
|
||||||
/* Check if any components have sent reply events to State. */
|
/* Check if any components have sent reply events to State. */
|
||||||
let events: Vec<UIEvent> = state.context.replies();
|
let events: ui::smallvec::SmallVec<[UIEvent; 8]> = state.context.replies();
|
||||||
for e in events {
|
for e in events {
|
||||||
state.rcv_event(e);
|
state.rcv_event(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
extern crate melib;
|
extern crate melib;
|
||||||
use melib::Result;
|
use melib::Result;
|
||||||
use melib::StackVec;
|
|
||||||
|
|
||||||
extern crate text_processing;
|
extern crate text_processing;
|
||||||
use text_processing::line_break::*;
|
use text_processing::line_break::*;
|
||||||
|
@ -14,14 +13,14 @@ fn cost(i: usize, j: usize, width: usize, minima: &Vec<usize>, offsets: &Vec<usi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn smawk(
|
fn smawk(
|
||||||
rows: &mut StackVec<usize>,
|
rows: &mut Vec<usize>,
|
||||||
columns: &mut StackVec<usize>,
|
columns: &mut Vec<usize>,
|
||||||
minima: &mut Vec<usize>,
|
minima: &mut Vec<usize>,
|
||||||
breaks: &mut Vec<usize>,
|
breaks: &mut Vec<usize>,
|
||||||
width: usize,
|
width: usize,
|
||||||
offsets: &Vec<usize>,
|
offsets: &Vec<usize>,
|
||||||
) {
|
) {
|
||||||
let mut stack = StackVec::new();
|
let mut stack = Vec::new();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < rows.len() {
|
while i < rows.len() {
|
||||||
if stack.len() > 0 {
|
if stack.len() > 0 {
|
||||||
|
@ -46,7 +45,7 @@ fn smawk(
|
||||||
let mut odd_columns = columns.iter().skip(1).step_by(2).cloned().collect();
|
let mut odd_columns = columns.iter().skip(1).step_by(2).cloned().collect();
|
||||||
smawk(rows, &mut odd_columns, minima, breaks, width, offsets);
|
smawk(rows, &mut odd_columns, minima, breaks, width, offsets);
|
||||||
for (i, o) in odd_columns.into_iter().enumerate() {
|
for (i, o) in odd_columns.into_iter().enumerate() {
|
||||||
columns.set(2 * i + 1, o);
|
columns[2 * i + 1] = o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
|
@ -30,6 +30,7 @@ rusqlite = {version = "0.20.0", optional =true }
|
||||||
rmp = "^0.8"
|
rmp = "^0.8"
|
||||||
rmpv = { version = "^0.4.2", features=["with-serde",] }
|
rmpv = { version = "^0.4.2", features=["with-serde",] }
|
||||||
rmp-serde = "^0.14.0"
|
rmp-serde = "^0.14.0"
|
||||||
|
smallvec = { version = "1.1.0", features = ["serde", ] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["sqlite3"]
|
default = ["sqlite3"]
|
||||||
|
|
|
@ -25,7 +25,7 @@ use melib::{
|
||||||
backends::{FolderHash, MailBackend},
|
backends::{FolderHash, MailBackend},
|
||||||
email::EnvelopeHash,
|
email::EnvelopeHash,
|
||||||
thread::{SortField, SortOrder},
|
thread::{SortField, SortOrder},
|
||||||
Result, StackVec,
|
Result,
|
||||||
};
|
};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ pub fn imap_search(
|
||||||
(_sort_field, _sort_order): (SortField, SortOrder),
|
(_sort_field, _sort_order): (SortField, SortOrder),
|
||||||
folder_hash: FolderHash,
|
folder_hash: FolderHash,
|
||||||
backend: &Arc<RwLock<Box<dyn MailBackend>>>,
|
backend: &Arc<RwLock<Box<dyn MailBackend>>>,
|
||||||
) -> Result<StackVec<EnvelopeHash>> {
|
) -> Result<smallvec::SmallVec<[EnvelopeHash; 512]>> {
|
||||||
let query = query().parse(term)?.1;
|
let query = query().parse(term)?.1;
|
||||||
let backend_lck = backend.read().unwrap();
|
let backend_lck = backend.read().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::types::segment_tree::SegmentTree;
|
use crate::types::segment_tree::SegmentTree;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
mod conversations;
|
mod conversations;
|
||||||
pub use self::conversations::*;
|
pub use self::conversations::*;
|
||||||
|
@ -56,10 +57,10 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
a: &ListingAction,
|
a: &ListingAction,
|
||||||
) {
|
) {
|
||||||
let account = &mut context.accounts[self.coordinates().0];
|
let account = &mut context.accounts[self.coordinates().0];
|
||||||
let mut envs_to_set: StackVec<EnvelopeHash> = StackVec::new();
|
let mut envs_to_set: SmallVec<[EnvelopeHash; 8]> = SmallVec::new();
|
||||||
let folder_hash = account[self.coordinates().1].unwrap().folder.hash();
|
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);
|
stack.push(thread_hash);
|
||||||
while let Some(thread_iter) = stack.pop() {
|
while let Some(thread_iter) = stack.pop() {
|
||||||
{
|
{
|
||||||
|
@ -138,8 +139,8 @@ pub trait MailListingTrait: ListingTrait {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row_updates(&mut self) -> &mut StackVec<ThreadHash>;
|
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]>;
|
||||||
fn get_focused_items(&self, _context: &Context) -> StackVec<ThreadHash>;
|
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ListingTrait: Component {
|
pub trait ListingTrait: Component {
|
||||||
|
|
|
@ -69,18 +69,18 @@ pub struct CompactListing {
|
||||||
/// If `self.view` exists or not.
|
/// If `self.view` exists or not.
|
||||||
unfocused: bool,
|
unfocused: bool,
|
||||||
view: ThreadView,
|
view: ThreadView,
|
||||||
row_updates: StackVec<ThreadHash>,
|
row_updates: SmallVec<[ThreadHash; 8]>,
|
||||||
|
|
||||||
movement: Option<PageMovement>,
|
movement: Option<PageMovement>,
|
||||||
id: ComponentId,
|
id: ComponentId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MailListingTrait for CompactListing {
|
impl MailListingTrait for CompactListing {
|
||||||
fn row_updates(&mut self) -> &mut StackVec<ThreadHash> {
|
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> {
|
||||||
&mut self.row_updates
|
&mut self.row_updates
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_focused_items(&self, context: &Context) -> StackVec<ThreadHash> {
|
fn get_focused_items(&self, context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
||||||
let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
|
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 i = [self.get_thread_under_cursor(self.cursor_pos.2, context)];
|
||||||
let cursor_iter;
|
let cursor_iter;
|
||||||
|
@ -96,7 +96,7 @@ impl MailListingTrait for CompactListing {
|
||||||
.flatten()
|
.flatten()
|
||||||
.chain(cursor_iter.into_iter().flatten())
|
.chain(cursor_iter.into_iter().flatten())
|
||||||
.cloned();
|
.cloned();
|
||||||
StackVec::from_iter(iter.into_iter())
|
SmallVec::from_iter(iter.into_iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ impl CompactListing {
|
||||||
filtered_selection: Vec::new(),
|
filtered_selection: Vec::new(),
|
||||||
filtered_order: FnvHashMap::default(),
|
filtered_order: FnvHashMap::default(),
|
||||||
selection: FnvHashMap::default(),
|
selection: FnvHashMap::default(),
|
||||||
row_updates: StackVec::new(),
|
row_updates: SmallVec::new(),
|
||||||
data_columns: DataColumns::default(),
|
data_columns: DataColumns::default(),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
force_draw: true,
|
force_draw: true,
|
||||||
|
@ -554,7 +554,7 @@ impl CompactListing {
|
||||||
.hash();
|
.hash();
|
||||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash];
|
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash];
|
||||||
let mut tags = String::new();
|
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();
|
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
|
@ -681,17 +681,17 @@ impl CompactListing {
|
||||||
let mut rows = Vec::with_capacity(1024);
|
let mut rows = Vec::with_capacity(1024);
|
||||||
let mut min_width = (0, 0, 0, 0, 0);
|
let mut min_width = (0, 0, 0, 0, 0);
|
||||||
let mut row_widths: (
|
let mut row_widths: (
|
||||||
StackVec<u8>,
|
SmallVec<[u8; 1024]>,
|
||||||
StackVec<u8>,
|
SmallVec<[u8; 1024]>,
|
||||||
StackVec<u8>,
|
SmallVec<[u8; 1024]>,
|
||||||
StackVec<u8>,
|
SmallVec<[u8; 1024]>,
|
||||||
StackVec<u8>,
|
SmallVec<[u8; 1024]>,
|
||||||
) = (
|
) = (
|
||||||
StackVec::new(),
|
SmallVec::new(),
|
||||||
StackVec::new(),
|
SmallVec::new(),
|
||||||
StackVec::new(),
|
SmallVec::new(),
|
||||||
StackVec::new(),
|
SmallVec::new(),
|
||||||
StackVec::new(),
|
SmallVec::new(),
|
||||||
);
|
);
|
||||||
|
|
||||||
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
|
threads.sort_by(self.sort, self.subsort, &account.collection.envelopes);
|
||||||
|
|
|
@ -73,7 +73,7 @@ column_str!(struct DateString(String));
|
||||||
column_str!(struct FromString(String));
|
column_str!(struct FromString(String));
|
||||||
column_str!(struct SubjectString(String));
|
column_str!(struct SubjectString(String));
|
||||||
column_str!(struct FlagString(String));
|
column_str!(struct FlagString(String));
|
||||||
column_str!(struct TagString(String, StackVec<Color>));
|
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
|
/// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a
|
||||||
/// `ThreadView`.
|
/// `ThreadView`.
|
||||||
|
@ -100,18 +100,18 @@ pub struct ConversationsListing {
|
||||||
/// If `self.view` exists or not.
|
/// If `self.view` exists or not.
|
||||||
unfocused: bool,
|
unfocused: bool,
|
||||||
view: ThreadView,
|
view: ThreadView,
|
||||||
row_updates: StackVec<ThreadHash>,
|
row_updates: SmallVec<[ThreadHash; 8]>,
|
||||||
|
|
||||||
movement: Option<PageMovement>,
|
movement: Option<PageMovement>,
|
||||||
id: ComponentId,
|
id: ComponentId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MailListingTrait for ConversationsListing {
|
impl MailListingTrait for ConversationsListing {
|
||||||
fn row_updates(&mut self) -> &mut StackVec<ThreadHash> {
|
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> {
|
||||||
&mut self.row_updates
|
&mut self.row_updates
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_focused_items(&self, context: &Context) -> StackVec<ThreadHash> {
|
fn get_focused_items(&self, context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
||||||
let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
|
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 i = [self.get_thread_under_cursor(self.cursor_pos.2, context)];
|
||||||
let cursor_iter;
|
let cursor_iter;
|
||||||
|
@ -127,7 +127,7 @@ impl MailListingTrait for ConversationsListing {
|
||||||
.flatten()
|
.flatten()
|
||||||
.chain(cursor_iter.into_iter().flatten())
|
.chain(cursor_iter.into_iter().flatten())
|
||||||
.cloned();
|
.cloned();
|
||||||
StackVec::from_iter(iter.into_iter())
|
SmallVec::from_iter(iter.into_iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ impl ConversationsListing {
|
||||||
filtered_selection: Vec::new(),
|
filtered_selection: Vec::new(),
|
||||||
filtered_order: FnvHashMap::default(),
|
filtered_order: FnvHashMap::default(),
|
||||||
selection: FnvHashMap::default(),
|
selection: FnvHashMap::default(),
|
||||||
row_updates: StackVec::new(),
|
row_updates: SmallVec::new(),
|
||||||
content: Default::default(),
|
content: Default::default(),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
force_draw: true,
|
force_draw: true,
|
||||||
|
@ -525,7 +525,7 @@ impl ConversationsListing {
|
||||||
.hash();
|
.hash();
|
||||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash];
|
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash];
|
||||||
let mut tags = String::new();
|
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();
|
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
|
@ -690,7 +690,7 @@ impl ConversationsListing {
|
||||||
}
|
}
|
||||||
from_address_list.clear();
|
from_address_list.clear();
|
||||||
from_address_set.clear();
|
from_address_set.clear();
|
||||||
let mut stack = StackVec::new();
|
let mut stack: SmallVec<[ThreadHash; 8]> = SmallVec::new();
|
||||||
stack.push(root_idx);
|
stack.push(root_idx);
|
||||||
while let Some(h) = stack.pop() {
|
while let Some(h) = stack.pop() {
|
||||||
let env_hash = if let Some(h) = threads.thread_nodes()[&h].message() {
|
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_list = Vec::new();
|
||||||
let mut from_address_set: std::collections::HashSet<Vec<u8>> =
|
let mut from_address_set: std::collections::HashSet<Vec<u8>> =
|
||||||
std::collections::HashSet::new();
|
std::collections::HashSet::new();
|
||||||
let mut stack = StackVec::new();
|
let mut stack: SmallVec<[ThreadHash; 8]> = SmallVec::new();
|
||||||
stack.push(thread_hash);
|
stack.push(thread_hash);
|
||||||
while let Some(h) = stack.pop() {
|
while let Some(h) = stack.pop() {
|
||||||
let env_hash = if let Some(h) = threads.thread_nodes()[&h].message() {
|
let env_hash = if let Some(h) = threads.thread_nodes()[&h].message() {
|
||||||
|
|
|
@ -70,19 +70,19 @@ pub struct PlainListing {
|
||||||
/// If `self.view` exists or not.
|
/// If `self.view` exists or not.
|
||||||
unfocused: bool,
|
unfocused: bool,
|
||||||
view: MailView,
|
view: MailView,
|
||||||
row_updates: StackVec<EnvelopeHash>,
|
row_updates: SmallVec<[EnvelopeHash; 8]>,
|
||||||
_row_updates: StackVec<ThreadHash>,
|
_row_updates: SmallVec<[ThreadHash; 8]>,
|
||||||
|
|
||||||
movement: Option<PageMovement>,
|
movement: Option<PageMovement>,
|
||||||
id: ComponentId,
|
id: ComponentId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MailListingTrait for PlainListing {
|
impl MailListingTrait for PlainListing {
|
||||||
fn row_updates(&mut self) -> &mut StackVec<ThreadHash> {
|
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> {
|
||||||
&mut self._row_updates
|
&mut self._row_updates
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_focused_items(&self, context: &Context) -> StackVec<ThreadHash> {
|
fn get_focused_items(&self, context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
||||||
let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
|
let is_selection_empty = self.selection.values().cloned().any(std::convert::identity);
|
||||||
if is_selection_empty {
|
if is_selection_empty {
|
||||||
self.selection
|
self.selection
|
||||||
|
@ -91,7 +91,7 @@ impl MailListingTrait for PlainListing {
|
||||||
.map(|(k, _)| self.thread_hashes[k])
|
.map(|(k, _)| self.thread_hashes[k])
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
let mut ret = StackVec::new();
|
let mut ret = SmallVec::new();
|
||||||
ret.push(self.get_thread_under_cursor(self.cursor_pos.2, context));
|
ret.push(self.get_thread_under_cursor(self.cursor_pos.2, context));
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
@ -484,8 +484,8 @@ impl PlainListing {
|
||||||
filtered_selection: Vec::new(),
|
filtered_selection: Vec::new(),
|
||||||
filtered_order: FnvHashMap::default(),
|
filtered_order: FnvHashMap::default(),
|
||||||
selection: FnvHashMap::default(),
|
selection: FnvHashMap::default(),
|
||||||
row_updates: StackVec::new(),
|
row_updates: SmallVec::new(),
|
||||||
_row_updates: StackVec::new(),
|
_row_updates: SmallVec::new(),
|
||||||
data_columns: DataColumns::default(),
|
data_columns: DataColumns::default(),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
force_draw: true,
|
force_draw: true,
|
||||||
|
@ -503,7 +503,7 @@ impl PlainListing {
|
||||||
.hash();
|
.hash();
|
||||||
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash];
|
let folder = &context.accounts[self.cursor_pos.0].folder_confs[&folder_hash];
|
||||||
let mut tags = String::new();
|
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();
|
let backend_lck = context.accounts[self.cursor_pos.0].backend.read().unwrap();
|
||||||
if let Some(t) = backend_lck.tags() {
|
if let Some(t) = backend_lck.tags() {
|
||||||
let tags_lck = t.read().unwrap();
|
let tags_lck = t.read().unwrap();
|
||||||
|
@ -1086,7 +1086,7 @@ impl Component for PlainListing {
|
||||||
.flatten()
|
.flatten()
|
||||||
.chain(cursor_iter.into_iter().flatten())
|
.chain(cursor_iter.into_iter().flatten())
|
||||||
.cloned();
|
.cloned();
|
||||||
let stack = StackVec::from_iter(iter.into_iter());
|
let stack: SmallVec<[_; 8]> = SmallVec::from_iter(iter.into_iter());
|
||||||
for i in stack {
|
for i in stack {
|
||||||
self.perform_action(context, i, a);
|
self.perform_action(context, i, a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub struct ThreadListing {
|
||||||
/// Cache current view.
|
/// Cache current view.
|
||||||
content: CellBuffer,
|
content: CellBuffer,
|
||||||
|
|
||||||
row_updates: StackVec<ThreadHash>,
|
row_updates: SmallVec<[ThreadHash; 8]>,
|
||||||
locations: Vec<EnvelopeHash>,
|
locations: Vec<EnvelopeHash>,
|
||||||
/// If we must redraw on next redraw event
|
/// If we must redraw on next redraw event
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
|
@ -50,12 +50,12 @@ pub struct ThreadListing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MailListingTrait for ThreadListing {
|
impl MailListingTrait for ThreadListing {
|
||||||
fn row_updates(&mut self) -> &mut StackVec<ThreadHash> {
|
fn row_updates(&mut self) -> &mut SmallVec<[ThreadHash; 8]> {
|
||||||
&mut self.row_updates
|
&mut self.row_updates
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_focused_items(&self, _context: &Context) -> StackVec<ThreadHash> {
|
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> {
|
||||||
StackVec::new()
|
SmallVec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ impl ThreadListing {
|
||||||
sort: (Default::default(), Default::default()),
|
sort: (Default::default(), Default::default()),
|
||||||
subsort: (Default::default(), Default::default()),
|
subsort: (Default::default(), Default::default()),
|
||||||
content,
|
content,
|
||||||
row_updates: StackVec::new(),
|
row_updates: SmallVec::new(),
|
||||||
locations: Vec::new(),
|
locations: Vec::new(),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
unfocused: false,
|
unfocused: false,
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use melib::list_management;
|
use melib::list_management;
|
||||||
use melib::parser::BytesExt;
|
use melib::parser::BytesExt;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
@ -229,7 +230,7 @@ impl MailView {
|
||||||
if body.count_attachments() > 1 {
|
if body.count_attachments() > 1 {
|
||||||
fn attachment_tree(
|
fn attachment_tree(
|
||||||
(idx, (depth, att)): (&mut usize, (usize, &Attachment)),
|
(idx, (depth, att)): (&mut usize, (usize, &Attachment)),
|
||||||
branches: &mut StackVec<bool>,
|
branches: &mut SmallVec<[bool; 8]>,
|
||||||
has_sibling: bool,
|
has_sibling: bool,
|
||||||
s: &mut String,
|
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
|
t
|
||||||
}
|
}
|
||||||
|
@ -1385,7 +1386,7 @@ impl Component for MailView {
|
||||||
}
|
}
|
||||||
_ => { /* error print message to user */ }
|
_ => { /* error print message to user */ }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
UIEvent::Action(Listing(OpenInNewTab)) => {
|
UIEvent::Action(Listing(OpenInNewTab)) => {
|
||||||
context
|
context
|
||||||
|
|
|
@ -848,7 +848,7 @@ impl ThreadView {
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.fold(
|
.fold(
|
||||||
(vec![Vec::new()], StackVec::new(), false),
|
(vec![Vec::new()], SmallVec::<[_; 8]>::new(), false),
|
||||||
|(mut visies, mut stack, is_prev_hidden), (idx, e)| {
|
|(mut visies, mut stack, is_prev_hidden), (idx, e)| {
|
||||||
match (e.hidden, is_prev_hidden) {
|
match (e.hidden, is_prev_hidden) {
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
|
|
|
@ -34,7 +34,7 @@ use melib::error::{MeliError, Result};
|
||||||
use melib::mailbox::*;
|
use melib::mailbox::*;
|
||||||
use melib::thread::{SortField, SortOrder, ThreadHash, ThreadNode, Threads};
|
use melib::thread::{SortField, SortOrder, ThreadHash, ThreadNode, Threads};
|
||||||
use melib::AddressBook;
|
use melib::AddressBook;
|
||||||
use melib::StackVec;
|
use smallvec::SmallVec;
|
||||||
use text_processing::GlobMatch;
|
use text_processing::GlobMatch;
|
||||||
|
|
||||||
use crate::types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification};
|
use crate::types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification};
|
||||||
|
@ -384,7 +384,7 @@ impl Account {
|
||||||
folder_names.insert(f.hash(), f.path().to_string());
|
folder_names.insert(f.hash(), f.path().to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stack: StackVec<FolderHash> = StackVec::new();
|
let mut stack: SmallVec<[FolderHash; 8]> = SmallVec::new();
|
||||||
let mut tree: Vec<FolderNode> = Vec::new();
|
let mut tree: Vec<FolderNode> = Vec::new();
|
||||||
let mut collection: Collection = Collection::new(Default::default());
|
let mut collection: Collection = Collection::new(Default::default());
|
||||||
for (h, f) in ref_folders.iter() {
|
for (h, f) in ref_folders.iter() {
|
||||||
|
@ -442,7 +442,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut stack: StackVec<Option<&FolderNode>> = StackVec::new();
|
let mut stack: SmallVec<[Option<&FolderNode>; 8]> = SmallVec::new();
|
||||||
for n in tree.iter_mut() {
|
for n in tree.iter_mut() {
|
||||||
folders_order.push(n.hash);
|
folders_order.push(n.hash);
|
||||||
n.kids.sort_unstable_by(|a, b| {
|
n.kids.sort_unstable_by(|a, b| {
|
||||||
|
@ -462,6 +462,7 @@ impl Account {
|
||||||
stack.extend(next.kids.iter().rev().map(Some));
|
stack.extend(next.kids.iter().rev().map(Some));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
drop(stack);
|
||||||
|
|
||||||
self.folders = folders;
|
self.folders = folders;
|
||||||
self.ref_folders = ref_folders;
|
self.ref_folders = ref_folders;
|
||||||
|
@ -1053,7 +1054,7 @@ impl Account {
|
||||||
search_term: &str,
|
search_term: &str,
|
||||||
sort: (SortField, SortOrder),
|
sort: (SortField, SortOrder),
|
||||||
folder_hash: FolderHash,
|
folder_hash: FolderHash,
|
||||||
) -> Result<StackVec<EnvelopeHash>> {
|
) -> Result<SmallVec<[EnvelopeHash; 512]>> {
|
||||||
if self.settings.account().format() == "imap" {
|
if self.settings.account().format() == "imap" {
|
||||||
return crate::cache::imap_search(search_term, sort, folder_hash, &self.backend);
|
return crate::cache::imap_search(search_term, sort, folder_hash, &self.backend);
|
||||||
}
|
}
|
||||||
|
@ -1081,7 +1082,7 @@ impl Account {
|
||||||
|
|
||||||
#[cfg(not(feature = "sqlite3"))]
|
#[cfg(not(feature = "sqlite3"))]
|
||||||
{
|
{
|
||||||
let mut ret = StackVec::new();
|
let mut ret = SmallVec::new();
|
||||||
let envelopes = self.collection.envelopes.clone().read();
|
let envelopes = self.collection.envelopes.clone().read();
|
||||||
let envelopes = envelopes.unwrap();
|
let envelopes = envelopes.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ extern crate termion;
|
||||||
extern crate nom;
|
extern crate nom;
|
||||||
|
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
pub extern crate smallvec;
|
||||||
|
|
||||||
use melib::*;
|
use melib::*;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use smallvec::SmallVec;
|
||||||
use crate::cache::query;
|
use crate::cache::query;
|
||||||
use crate::cache::Query::{self, *};
|
use crate::cache::Query::{self, *};
|
||||||
use crate::melib::parsec::Parser;
|
use crate::melib::parsec::Parser;
|
||||||
|
@ -27,7 +28,7 @@ use melib::{
|
||||||
email::{Envelope, EnvelopeHash},
|
email::{Envelope, EnvelopeHash},
|
||||||
log,
|
log,
|
||||||
thread::{SortField, SortOrder},
|
thread::{SortField, SortOrder},
|
||||||
MeliError, Result, StackVec, ERROR,
|
MeliError, Result, ERROR,
|
||||||
};
|
};
|
||||||
use rusqlite::{params, Connection};
|
use rusqlite::{params, Connection};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
@ -389,7 +390,7 @@ pub fn index(context: &mut crate::state::Context, account_name: &str) -> Result<
|
||||||
pub fn search(
|
pub fn search(
|
||||||
term: &str,
|
term: &str,
|
||||||
(sort_field, sort_order): (SortField, SortOrder),
|
(sort_field, sort_order): (SortField, SortOrder),
|
||||||
) -> Result<StackVec<EnvelopeHash>> {
|
) -> Result<SmallVec<[EnvelopeHash; 512]>> {
|
||||||
let conn = open_db()?;
|
let conn = open_db()?;
|
||||||
|
|
||||||
let sort_field = match debug!(sort_field) {
|
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()))?,
|
.map_err(|e: std::array::TryFromSliceError| MeliError::new(e.to_string()))?,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.collect::<Result<StackVec<EnvelopeHash>>>();
|
.collect::<Result<SmallVec<[EnvelopeHash; 512]>>>();
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ pub struct Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn replies(&mut self) -> Vec<UIEvent> {
|
pub fn replies(&mut self) -> smallvec::SmallVec<[UIEvent; 8]> {
|
||||||
self.replies.drain(0..).collect()
|
self.replies.drain(0..).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,7 +437,8 @@ impl State {
|
||||||
for i in 0..self.components.len() {
|
for i in 0..self.components.len() {
|
||||||
self.draw_component(i);
|
self.draw_component(i);
|
||||||
}
|
}
|
||||||
let mut areas: Vec<Area> = 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() {
|
if areas.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -682,7 +683,8 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.context.replies.is_empty() {
|
if !self.context.replies.is_empty() {
|
||||||
let replies: Vec<UIEvent> = 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
|
// Pass replies to self and call count on the map iterator to force evaluation
|
||||||
replies.into_iter().map(|r| self.rcv_event(r)).count();
|
replies.into_iter().map(|r| self.rcv_event(r)).count();
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,24 +152,24 @@ pub mod segment_tree {
|
||||||
/*! Simple segment tree implementation for maximum in range queries. This is useful if given an
|
/*! 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.
|
* 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::convert::TryFrom;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct SegmentTree {
|
pub struct SegmentTree {
|
||||||
array: StackVec<u8>,
|
array: SmallVec<[u8; 1024]>,
|
||||||
tree: StackVec<u8>,
|
tree: SmallVec<[u8; 1024]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StackVec<u8>> for SegmentTree {
|
impl From<SmallVec<[u8; 1024]>> for SegmentTree {
|
||||||
fn from(val: StackVec<u8>) -> SegmentTree {
|
fn from(val: SmallVec<[u8; 1024]>) -> SegmentTree {
|
||||||
SegmentTree::new(val)
|
SegmentTree::new(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SegmentTree {
|
impl SegmentTree {
|
||||||
pub fn new(val: StackVec<u8>) -> SegmentTree {
|
pub fn new(val: SmallVec<[u8; 1024]>) -> SegmentTree {
|
||||||
if val.is_empty() {
|
if val.is_empty() {
|
||||||
return SegmentTree {
|
return SegmentTree {
|
||||||
array: val.clone(),
|
array: val.clone(),
|
||||||
|
@ -182,8 +182,8 @@ pub mod segment_tree {
|
||||||
.ceil() as u32;
|
.ceil() as u32;
|
||||||
let max_size = 2 * (2_usize.pow(height)) - 1;
|
let max_size = 2 * (2_usize.pow(height)) - 1;
|
||||||
|
|
||||||
let mut segment_tree: StackVec<u8> =
|
let mut segment_tree: SmallVec<[u8; 1024]> =
|
||||||
StackVec::from_iter(core::iter::repeat(0).take(max_size));
|
SmallVec::from_iter(core::iter::repeat(0).take(max_size));
|
||||||
for i in 0..val.len() {
|
for i in 0..val.len() {
|
||||||
segment_tree[val.len() + i] = val[i];
|
segment_tree[val.len() + i] = val[i];
|
||||||
}
|
}
|
||||||
|
@ -231,10 +231,10 @@ pub mod segment_tree {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_segment_tree() {
|
fn test_segment_tree() {
|
||||||
let array: StackVec<u8> = [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()
|
.into_iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<StackVec<u8>>();
|
.collect::<SmallVec<[u8; 1024]>>();
|
||||||
let segment_tree = SegmentTree::from(array.clone());
|
let segment_tree = SegmentTree::from(array.clone());
|
||||||
|
|
||||||
assert_eq!(segment_tree.get_max(0, 5), 23);
|
assert_eq!(segment_tree.get_max(0, 5), 23);
|
||||||
|
|
Loading…
Reference in New Issue