diff --git a/melib/src/lib.rs b/melib/src/lib.rs index 6151cbcd..4e2d2949 100644 --- a/melib/src/lib.rs +++ b/melib/src/lib.rs @@ -86,6 +86,8 @@ pub mod mailbox; mod wcwidth; pub use self::grapheme_clusters::*; pub use self::wcwidth::*; +mod structs; +pub use self::structs::*; #[macro_use] extern crate serde_derive; diff --git a/melib/src/mailbox/thread.rs b/melib/src/mailbox/thread.rs index 79cb1600..287b24b1 100644 --- a/melib/src/mailbox/thread.rs +++ b/melib/src/mailbox/thread.rs @@ -35,6 +35,7 @@ use crate::grapheme_clusters::*; use crate::mailbox::email::parser::BytesExt; use crate::mailbox::email::*; +use crate::structs::StackVec; use uuid::Uuid; use fnv::{FnvHashMap, FnvHashSet}; @@ -350,7 +351,7 @@ impl ThreadTree { pub struct ThreadsIterator<'a> { pos: usize, - stack: Vec, + stack: StackVec, tree: Ref<'a, Vec>, } impl<'a> Iterator for ThreadsIterator<'a> { @@ -358,7 +359,7 @@ impl<'a> Iterator for ThreadsIterator<'a> { fn next(&mut self) -> Option<(usize, ThreadHash, bool)> { { let mut tree = &(*self.tree); - for i in &self.stack { + for i in self.stack.iter() { tree = &tree[*i].children; } if self.pos == tree.len() { @@ -402,7 +403,7 @@ impl<'a> Iterator for ThreadsIterator<'a> { pub struct ThreadIterator<'a> { init_pos: usize, pos: usize, - stack: Vec, + stack: StackVec, tree: Ref<'a, Vec>, } impl<'a> Iterator for ThreadIterator<'a> { @@ -410,7 +411,7 @@ impl<'a> Iterator for ThreadIterator<'a> { fn next(&mut self) -> Option<(usize, ThreadHash)> { { let mut tree = &(*self.tree); - for i in &self.stack { + for i in self.stack.iter() { tree = &tree[*i].children; } if self.pos == tree.len() || (self.stack.is_empty() && self.pos > self.init_pos) { @@ -823,7 +824,7 @@ impl Threads { pub fn threads_iter(&self) -> ThreadsIterator { ThreadsIterator { pos: 0, - stack: Vec::with_capacity(4), + stack: StackVec::new(), tree: self.tree.borrow(), } } @@ -832,7 +833,7 @@ impl Threads { ThreadIterator { init_pos: index, pos: index, - stack: Vec::with_capacity(4), + stack: StackVec::new(), tree: self.tree.borrow(), } } @@ -1057,7 +1058,7 @@ impl Threads { /* Update thread tree information on envelope insertion */ fn rebuild_thread(&mut self, id: ThreadHash, envelopes: &Envelopes) { let mut node_idx = id; - let mut stack = Vec::with_capacity(32); + let mut stack = StackVec::new(); { let tree = self.tree.get_mut(); diff --git a/melib/src/structs.rs b/melib/src/structs.rs new file mode 100644 index 00000000..e725f209 --- /dev/null +++ b/melib/src/structs.rs @@ -0,0 +1,115 @@ +use std::iter::Extend; +use std::ops::Index; + +#[derive(Debug)] +pub struct StackVec { + len: usize, + array: [T; 32], + heap_vec: Vec, +} + +impl StackVec { + pub fn new() -> Self { + StackVec { + len: 0, + array: [T::default(); 32], + 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(32); + for _ in 0..8 { + self.heap_vec.push(T::default()); + } + } + self.heap_vec[0..8].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 = 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 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 Extend for StackVec { + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + for elem in iter { + self.push(elem); + } + } +} diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs index 7c78d9cc..6c7ee294 100644 --- a/ui/src/conf/accounts.rs +++ b/ui/src/conf/accounts.rs @@ -25,7 +25,6 @@ use super::AccountConf; use super::ToggleFlag; -use crate::StackVec; use fnv::FnvHashMap; use melib::async_workers::{Async, AsyncBuilder, AsyncStatus}; use melib::backends::FolderHash; @@ -37,6 +36,7 @@ use melib::mailbox::backends::{ use melib::mailbox::*; use melib::thread::ThreadHash; use melib::AddressBook; +use melib::StackVec; use std::collections::VecDeque; use std::fs; diff --git a/ui/src/types.rs b/ui/src/types.rs index fd993321..b1a6c431 100644 --- a/ui/src/types.rs +++ b/ui/src/types.rs @@ -30,8 +30,6 @@ use melib::backends::FolderHash; use melib::{EnvelopeHash, RefreshEvent}; use std; use std::fmt; -use std::iter::Extend; -use std::ops::Index; use std::thread; use uuid::Uuid; @@ -129,79 +127,3 @@ pub struct Notification { _timestamp: std::time::Instant, } - -#[derive(Debug)] -pub(crate) struct StackVec { - len: usize, - array: [T; 32], - heap_vec: Vec, -} - -impl StackVec { - pub(crate) fn new() -> Self { - StackVec { - len: 0, - array: [T::default(); 32], - heap_vec: Vec::new(), - } - } - pub(crate) fn push(&mut self, ind: T) { - if self.len == self.array.len() { - if self.heap_vec.is_empty() { - self.heap_vec.reserve(32); - for _ in 0..8 { - self.heap_vec.push(T::default()); - } - } - self.heap_vec[0..8].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(crate) 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 = self.len - 1; - Some(ret) - } - } - pub(crate) fn len(&self) -> usize { - self.len - } - pub(crate) fn is_empty(&self) -> bool { - self.len == 0 - } -} - -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 Extend for StackVec { - fn extend(&mut self, iter: I) - where - I: IntoIterator, - { - for elem in iter { - self.push(elem); - } - } -}