ui: Refer to child/parents with FolderHash in BackendFolder
- use a stack to build folder order list in conf/accounts.rs - update side menu printembed
parent
596194fa47
commit
1e44089d84
|
@ -239,12 +239,13 @@ pub trait BackendFolder: Debug {
|
|||
fn name(&self) -> &str;
|
||||
fn change_name(&mut self, new_name: &str);
|
||||
fn clone(&self) -> Folder;
|
||||
fn children(&self) -> &Vec<usize>;
|
||||
fn children(&self) -> &Vec<FolderHash>;
|
||||
fn parent(&self) -> Option<FolderHash>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DummyFolder {
|
||||
v: Vec<usize>,
|
||||
v: Vec<FolderHash>,
|
||||
}
|
||||
|
||||
impl BackendFolder for DummyFolder {
|
||||
|
@ -262,9 +263,13 @@ impl BackendFolder for DummyFolder {
|
|||
folder_default()
|
||||
}
|
||||
|
||||
fn children(&self) -> &Vec<usize> {
|
||||
fn children(&self) -> &Vec<FolderHash> {
|
||||
&self.v
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<FolderHash> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn folder_default() -> Folder {
|
||||
|
|
|
@ -193,11 +193,17 @@ pub struct MaildirFolder {
|
|||
hash: FolderHash,
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
children: Vec<usize>,
|
||||
parent: Option<FolderHash>,
|
||||
children: Vec<FolderHash>,
|
||||
}
|
||||
|
||||
impl MaildirFolder {
|
||||
pub fn new(path: String, file_name: String, children: Vec<usize>) -> Result<Self> {
|
||||
pub fn new(
|
||||
path: String,
|
||||
file_name: String,
|
||||
parent: Option<FolderHash>,
|
||||
children: Vec<FolderHash>,
|
||||
) -> Result<Self> {
|
||||
let pathbuf = PathBuf::from(path);
|
||||
let mut h = DefaultHasher::new();
|
||||
pathbuf.hash(&mut h);
|
||||
|
@ -206,6 +212,7 @@ impl MaildirFolder {
|
|||
hash: h.finish(),
|
||||
name: file_name,
|
||||
path: pathbuf,
|
||||
parent,
|
||||
children,
|
||||
};
|
||||
ret.is_valid()?;
|
||||
|
@ -243,7 +250,7 @@ impl BackendFolder for MaildirFolder {
|
|||
self.name = s.to_string();
|
||||
}
|
||||
|
||||
fn children(&self) -> &Vec<usize> {
|
||||
fn children(&self) -> &Vec<FolderHash> {
|
||||
&self.children
|
||||
}
|
||||
|
||||
|
@ -253,6 +260,11 @@ impl BackendFolder for MaildirFolder {
|
|||
name: self.name.clone(),
|
||||
path: self.path.clone(),
|
||||
children: self.children.clone(),
|
||||
parent: self.parent.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
fn parent(&self) -> Option<FolderHash> {
|
||||
self.parent.clone()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ pub type HashIndexes = Arc<Mutex<FnvHashMap<FolderHash, HashIndex>>>;
|
|||
#[derive(Debug)]
|
||||
pub struct MaildirType {
|
||||
name: String,
|
||||
folders: Vec<MaildirFolder>,
|
||||
folders: FnvHashMap<FolderHash, MaildirFolder>,
|
||||
//folder_index: FnvHashMap<FolderHash, usize>,
|
||||
hash_indexes: HashIndexes,
|
||||
path: PathBuf,
|
||||
|
@ -144,7 +144,10 @@ fn move_to_cur(p: PathBuf) -> PathBuf {
|
|||
|
||||
impl MailBackend for MaildirType {
|
||||
fn folders(&self) -> FnvHashMap<FolderHash, Folder> {
|
||||
self.folders.iter().map(|f| (f.hash(), f.clone())).collect()
|
||||
self.folders
|
||||
.iter()
|
||||
.map(|(h, f)| (*h, f.clone() as Folder))
|
||||
.collect()
|
||||
}
|
||||
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>> {
|
||||
self.multicore(4, folder)
|
||||
|
@ -417,7 +420,7 @@ eprintln!("removed but not contained in index");
|
|||
}
|
||||
|
||||
fn save(&self, bytes: &[u8], folder: &str) -> Result<()> {
|
||||
for f in &self.folders {
|
||||
for f in self.folders.values() {
|
||||
if f.name == folder {
|
||||
let mut path = f.path.clone();
|
||||
path.push("cur");
|
||||
|
@ -464,25 +467,34 @@ eprintln!("removed but not contained in index");
|
|||
|
||||
impl MaildirType {
|
||||
pub fn new(f: &AccountSettings) -> Self {
|
||||
let mut folders: Vec<MaildirFolder> = Vec::new();
|
||||
fn recurse_folders<P: AsRef<Path>>(folders: &mut Vec<MaildirFolder>, p: P) -> Vec<usize> {
|
||||
let name = f.name.clone();
|
||||
let mut folders: FnvHashMap<FolderHash, MaildirFolder> = Default::default();
|
||||
fn recurse_folders<P: AsRef<Path>>(
|
||||
folders: &mut FnvHashMap<FolderHash, MaildirFolder>,
|
||||
p: P,
|
||||
) -> Vec<FolderHash> {
|
||||
let mut children = Vec::new();
|
||||
for mut f in fs::read_dir(p).unwrap() {
|
||||
for f in f.iter_mut() {
|
||||
'entries: for f in f.iter_mut() {
|
||||
{
|
||||
let path = f.path();
|
||||
if path.ends_with("cur") || path.ends_with("new") || path.ends_with("tmp") {
|
||||
continue;
|
||||
continue 'entries;
|
||||
}
|
||||
if path.is_dir() {
|
||||
let path_children = recurse_folders(folders, &path);
|
||||
let path_children = std::dbg!(recurse_folders(folders, &path));
|
||||
if let Ok(f) = MaildirFolder::new(
|
||||
path.to_str().unwrap().to_string(),
|
||||
path.file_name().unwrap().to_str().unwrap().to_string(),
|
||||
None,
|
||||
path_children,
|
||||
) {
|
||||
folders.push(f);
|
||||
children.push(folders.len() - 1);
|
||||
f.children
|
||||
.iter()
|
||||
.map(|c| folders.get_mut(c).map(|f| f.parent = Some(f.hash)))
|
||||
.count();
|
||||
children.push(f.hash);
|
||||
folders.insert(f.hash, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,18 +507,28 @@ impl MaildirType {
|
|||
if let Ok(f) = MaildirFolder::new(
|
||||
path.to_str().unwrap().to_string(),
|
||||
path.file_name().unwrap().to_str().unwrap().to_string(),
|
||||
None,
|
||||
Vec::with_capacity(0),
|
||||
) {
|
||||
if f.is_valid().is_ok() {
|
||||
folders.push(f);
|
||||
}
|
||||
let l: MaildirFolder = f;
|
||||
folders.insert(l.hash, l);
|
||||
}
|
||||
}
|
||||
|
||||
if folders.is_empty() {
|
||||
recurse_folders(&mut folders, &path);
|
||||
let children = recurse_folders(&mut folders, &path);
|
||||
children
|
||||
.iter()
|
||||
.map(|c| folders.get_mut(c).map(|f| f.parent = None))
|
||||
.count();
|
||||
} else {
|
||||
folders[0].children = recurse_folders(&mut folders, &path);
|
||||
let root_hash = *folders.keys().nth(0).unwrap();
|
||||
let children = recurse_folders(&mut folders, &path);
|
||||
children
|
||||
.iter()
|
||||
.map(|c| folders.get_mut(c).map(|f| f.parent = Some(root_hash)))
|
||||
.count();
|
||||
folders.get_mut(&root_hash).map(|f| f.children = children);
|
||||
}
|
||||
|
||||
let hash_indexes = Arc::new(Mutex::new(FnvHashMap::with_capacity_and_hasher(
|
||||
|
@ -515,12 +537,12 @@ impl MaildirType {
|
|||
)));
|
||||
{
|
||||
let mut hash_indexes = hash_indexes.lock().unwrap();
|
||||
for f in &folders {
|
||||
for &fh in folders.keys() {
|
||||
hash_indexes.insert(
|
||||
f.hash(),
|
||||
fh,
|
||||
HashIndex {
|
||||
index: FnvHashMap::with_capacity_and_hasher(0, Default::default()),
|
||||
hash: f.hash(),
|
||||
hash: fh,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -532,10 +554,10 @@ impl MaildirType {
|
|||
path: PathBuf::from(f.root_folder()),
|
||||
}
|
||||
}
|
||||
fn owned_folder_idx(&self, folder: &Folder) -> usize {
|
||||
self.folders
|
||||
fn owned_folder_idx(&self, folder: &Folder) -> FolderHash {
|
||||
*self
|
||||
.folders
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, f)| f.hash() == folder.hash())
|
||||
.unwrap()
|
||||
.0
|
||||
|
@ -548,7 +570,7 @@ impl MaildirType {
|
|||
let handle = {
|
||||
let tx = w.tx();
|
||||
// TODO: Avoid clone
|
||||
let folder: &MaildirFolder = &self.folders[self.owned_folder_idx(folder)];
|
||||
let folder: &MaildirFolder = &self.folders[&self.owned_folder_idx(folder)];
|
||||
let folder_hash = folder.hash();
|
||||
let tx_final = w.tx();
|
||||
let path: PathBuf = folder.path().into();
|
||||
|
|
|
@ -43,7 +43,6 @@ pub use contacts::*;
|
|||
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use fnv::FnvHashMap;
|
||||
use uuid::Uuid;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
use super::*;
|
||||
use melib::backends::Folder;
|
||||
use melib::backends::FolderHash;
|
||||
|
||||
pub mod listing;
|
||||
pub use listing::*;
|
||||
|
@ -91,35 +92,23 @@ impl AccountMenu {
|
|||
eprintln!("BUG: invalid area in print_account");
|
||||
}
|
||||
// Each entry and its index in the account
|
||||
let entries: Vec<(usize, Folder)> = {
|
||||
let a = &context.accounts[a.index];
|
||||
let mut entries = Vec::with_capacity(a.len());
|
||||
for (idx, acc) in a.list_folders().into_iter().enumerate() {
|
||||
entries.push((idx, acc));
|
||||
}
|
||||
entries
|
||||
};
|
||||
let entries: FnvHashMap<FolderHash, Folder> = context.accounts[a.index]
|
||||
.list_folders()
|
||||
.into_iter()
|
||||
.map(|f| (f.hash(), f))
|
||||
.collect();
|
||||
let folders_order: FnvHashMap<FolderHash, usize> = context.accounts[a.index]
|
||||
.folders_order()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, &fh)| (fh, i))
|
||||
.collect();
|
||||
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
|
||||
let highlight = self.cursor.map(|(x, _)| x == a.index).unwrap_or(false);
|
||||
|
||||
let mut parents: Vec<Option<usize>> = vec![None; entries.len()];
|
||||
|
||||
for (idx, e) in entries.iter().enumerate() {
|
||||
for &c in e.1.children() {
|
||||
if c < parents.len() {
|
||||
parents[c] = Some(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut roots = Vec::new();
|
||||
for (idx, c) in parents.iter().enumerate() {
|
||||
if c.is_none() {
|
||||
roots.push(idx);
|
||||
}
|
||||
}
|
||||
|
||||
let mut inc = 0;
|
||||
let mut depth = String::from("");
|
||||
let mut s = format!("{}\n", a.name);
|
||||
|
@ -133,50 +122,72 @@ impl AccountMenu {
|
|||
}
|
||||
|
||||
fn print(
|
||||
root: usize,
|
||||
parents: &[Option<usize>],
|
||||
folder_idx: FolderHash,
|
||||
depth: &mut String,
|
||||
entries: &[(usize, Folder)],
|
||||
s: &mut String,
|
||||
inc: &mut usize,
|
||||
entries: &FnvHashMap<FolderHash, Folder>,
|
||||
folders_order: &FnvHashMap<FolderHash, usize>,
|
||||
s: &mut String,
|
||||
index: usize, //account index
|
||||
context: &mut Context,
|
||||
) {
|
||||
if root >= entries.len() {
|
||||
return;
|
||||
}
|
||||
let len = s.len();
|
||||
match context.accounts[index].status(entries[root].1.hash()) {
|
||||
Ok(_) => {}
|
||||
match context.accounts[index].status(entries[&folder_idx].hash()) {
|
||||
Ok(_) => {
|
||||
let count = context.accounts[index][entries[&folder_idx].hash()]
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.collection
|
||||
.values()
|
||||
.filter(|e| !e.is_seen())
|
||||
.count();
|
||||
let len = s.len();
|
||||
s.insert_str(
|
||||
len,
|
||||
&format!("{} {} {}\n ", *inc, &entries[&folder_idx].name(), count),
|
||||
);
|
||||
}
|
||||
Err(_) => {
|
||||
return;
|
||||
// TODO: Show progress visually
|
||||
let len = s.len();
|
||||
s.insert_str(
|
||||
len,
|
||||
&format!("{} {} ...\n ", *inc, &entries[&folder_idx].name()),
|
||||
);
|
||||
}
|
||||
}
|
||||
let count = context.accounts[index][root]
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.collection
|
||||
.values()
|
||||
.filter(|e| !e.is_seen())
|
||||
.count();
|
||||
s.insert_str(
|
||||
len,
|
||||
&format!("{} {} {}\n ", *inc, &entries[root].1.name(), count),
|
||||
);
|
||||
*inc += 1;
|
||||
for child in entries[root].1.children().iter() {
|
||||
let mut children: Vec<FolderHash> = entries[&folder_idx].children().to_vec();
|
||||
children
|
||||
.sort_unstable_by(|a, b| folders_order[a].partial_cmp(&folders_order[b]).unwrap());
|
||||
for child in entries[&folder_idx].children().iter() {
|
||||
let len = s.len();
|
||||
s.insert_str(len, &format!("{} ", depth));
|
||||
push(depth, ' ');
|
||||
print(*child, parents, depth, entries, s, inc, index, context);
|
||||
print(
|
||||
*child,
|
||||
depth,
|
||||
inc,
|
||||
entries,
|
||||
folders_order,
|
||||
s,
|
||||
index,
|
||||
context,
|
||||
);
|
||||
pop(depth);
|
||||
}
|
||||
}
|
||||
for r in roots {
|
||||
print(
|
||||
r, &parents, &mut depth, &entries, &mut s, &mut inc, a.index, context,
|
||||
);
|
||||
for f in entries.keys() {
|
||||
if entries[f].parent().is_none() {
|
||||
print(
|
||||
*f,
|
||||
&mut depth,
|
||||
&mut inc,
|
||||
&entries,
|
||||
&folders_order,
|
||||
&mut s,
|
||||
a.index,
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let lines: Vec<&str> = s.lines().collect();
|
||||
|
|
|
@ -54,63 +54,6 @@ pub struct ThreadView {
|
|||
id: ComponentId,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct StackVec {
|
||||
len: usize,
|
||||
array: [usize; 8],
|
||||
heap_vec: Vec<usize>,
|
||||
}
|
||||
|
||||
impl StackVec {
|
||||
fn new() -> Self {
|
||||
StackVec {
|
||||
len: 0,
|
||||
array: [0, 0, 0, 0, 0, 0, 0, 0],
|
||||
heap_vec: Vec::new(),
|
||||
}
|
||||
}
|
||||
fn push(&mut self, ind: usize) {
|
||||
if self.len == self.array.len() {
|
||||
self.heap_vec.clear();
|
||||
self.heap_vec.reserve(16);
|
||||
self.heap_vec.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;
|
||||
}
|
||||
fn pop(&mut self) -> usize {
|
||||
if self.len >= self.array.len() {
|
||||
self.heap_vec.pop().unwrap()
|
||||
} else {
|
||||
let ret = self.array[self.len];
|
||||
self.len = self.len.saturating_sub(1);
|
||||
ret
|
||||
}
|
||||
}
|
||||
fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<usize> for StackVec {
|
||||
type Output = usize;
|
||||
|
||||
fn index(&self, idx: usize) -> &usize {
|
||||
if self.len >= self.array.len() {
|
||||
&self.heap_vec[idx]
|
||||
} else {
|
||||
&self.array[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ThreadView {
|
||||
/*
|
||||
* coordinates: (account index, mailbox index, root set thread_node index)
|
||||
|
@ -133,7 +76,8 @@ impl ThreadView {
|
|||
cursor_pos: 1,
|
||||
new_cursor_pos: 0,
|
||||
dirty: true,
|
||||
id: ComponentId::new_v4(), ..Default::default()
|
||||
id: ComponentId::new_v4(),
|
||||
..Default::default()
|
||||
};
|
||||
view.initiate(expanded_idx, context);
|
||||
view.new_cursor_pos = view.new_expanded_pos;
|
||||
|
@ -875,7 +819,7 @@ impl Component for ThreadView {
|
|||
.operation(envelope.hash(), mailbox.folder.hash());
|
||||
if cfg!(debug_assertions) {
|
||||
eprint!("{}:{}_{}: ", file!(), line!(), column!());
|
||||
eprintln!(
|
||||
eprintln!(
|
||||
"sending action edit for {}, {}",
|
||||
envelope.message_id(),
|
||||
op.description()
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
use super::AccountConf;
|
||||
use crate::StackVec;
|
||||
use fnv::FnvHashMap;
|
||||
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus};
|
||||
use melib::backends::FolderHash;
|
||||
|
@ -69,7 +70,7 @@ pub struct Account {
|
|||
|
||||
pub(crate) settings: AccountConf,
|
||||
pub(crate) runtime_settings: AccountConf,
|
||||
pub(crate) backend: Box<MailBackend>,
|
||||
pub(crate) backend: Box<dyn MailBackend>,
|
||||
notify_fn: Arc<NotifyFn>,
|
||||
}
|
||||
|
||||
|
@ -128,19 +129,10 @@ impl Account {
|
|||
let mut ref_folders: FnvHashMap<FolderHash, Folder> = backend.folders();
|
||||
let mut folders: FnvHashMap<FolderHash, Option<Result<Mailbox>>> =
|
||||
FnvHashMap::with_capacity_and_hasher(ref_folders.len(), Default::default());
|
||||
let mut folders_order: Vec<FolderHash> = ref_folders.values().map(|f| f.hash()).collect();
|
||||
let mut folders_order: Vec<FolderHash> = Vec::with_capacity(folders.len());
|
||||
let mut workers: FnvHashMap<FolderHash, Worker> = FnvHashMap::default();
|
||||
let notify_fn = Arc::new(notify_fn);
|
||||
|
||||
if let Some(pos) = ref_folders
|
||||
.values()
|
||||
.position(|f| f.name().eq_ignore_ascii_case("INBOX"))
|
||||
{
|
||||
folders_order.swap(pos, 0);
|
||||
}
|
||||
let sent_folder = ref_folders
|
||||
.values()
|
||||
.position(|x: &Folder| x.name() == settings.account().sent_folder);
|
||||
if let Some(folder_confs) = settings.conf().folders() {
|
||||
//if cfg!(debug_assertions) {
|
||||
//eprint!("{}:{}_{}: ", file!(), line!(), column!());
|
||||
|
@ -154,10 +146,28 @@ impl Account {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (h, f) in ref_folders.into_iter() {
|
||||
folders.insert(h, None);
|
||||
workers.insert(h, Account::new_worker(f, &mut backend, notify_fn.clone()));
|
||||
let mut stack: StackVec<FolderHash> = StackVec::new();
|
||||
for (h, f) in ref_folders.iter() {
|
||||
if f.parent().is_none() {
|
||||
folders_order.push(f.hash());
|
||||
for &c in f.children() {
|
||||
stack.push(c);
|
||||
}
|
||||
while !stack.is_empty() {
|
||||
let next = stack.pop();
|
||||
folders_order.push(next);
|
||||
for c in ref_folders[&next].children() {
|
||||
stack.push(*c);
|
||||
}
|
||||
}
|
||||
}
|
||||
folders.insert(*h, None);
|
||||
workers.insert(
|
||||
*h,
|
||||
Account::new_worker(f.clone(), &mut backend, notify_fn.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
let data_dir = xdg::BaseDirectories::with_profile("meli", &name).unwrap();
|
||||
let address_book = if let Ok(data) = data_dir.place_data_file("addressbook") {
|
||||
if data.exists() {
|
||||
|
@ -180,7 +190,7 @@ impl Account {
|
|||
folders,
|
||||
folders_order,
|
||||
address_book,
|
||||
sent_folder,
|
||||
sent_folder: None,
|
||||
workers,
|
||||
settings: settings.clone(),
|
||||
runtime_settings: settings,
|
||||
|
@ -295,10 +305,18 @@ impl Account {
|
|||
folders.swap(pos, 0);
|
||||
}
|
||||
*/
|
||||
self.folders_order
|
||||
let order: FnvHashMap<FolderHash, usize> = self
|
||||
.folders_order
|
||||
.iter()
|
||||
.map(|ref h| folders.remove(&h).unwrap())
|
||||
.collect()
|
||||
.enumerate()
|
||||
.map(|(i, &fh)| (fh, i))
|
||||
.collect();
|
||||
let mut folders: Vec<Folder> = folders.drain().map(|(_, f)| f).collect();
|
||||
folders.sort_unstable_by(|a, b| order[&a.hash()].partial_cmp(&order[&b.hash()]).unwrap());
|
||||
folders
|
||||
}
|
||||
pub fn folders_order(&self) -> &Vec<FolderHash> {
|
||||
&self.folders_order
|
||||
}
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
|
|
|
@ -31,6 +31,7 @@ use melib::EnvelopeHash;
|
|||
use melib::RefreshEvent;
|
||||
use std;
|
||||
use std::fmt;
|
||||
use std::ops::Index;
|
||||
use std::thread;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -128,3 +129,65 @@ pub struct Notification {
|
|||
|
||||
_timestamp: std::time::Instant,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct StackVec<T: Default + Copy + std::fmt::Debug> {
|
||||
len: usize,
|
||||
array: [T; 8],
|
||||
heap_vec: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Default + Copy + std::fmt::Debug> StackVec<T> {
|
||||
pub(crate) fn new() -> Self {
|
||||
StackVec {
|
||||
len: 0,
|
||||
array: [T::default(); 8],
|
||||
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(16);
|
||||
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) -> T {
|
||||
if self.len >= self.array.len() {
|
||||
self.len -= 1;
|
||||
self.heap_vec.pop().unwrap()
|
||||
} else {
|
||||
let ret = self.array[self.len - 1];
|
||||
self.len = self.len - 1;
|
||||
ret
|
||||
}
|
||||
}
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue