/*
* meli - mailbox threading module.
*
* Copyright 2017 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/>.
*/
/*!
* This module implements Jamie Zawinski's (threading algorithm)
* [https://www.jwz.org/doc/threading.html]. It is a bit of a beast, so prepare for a lot of
* bloated code that's necessary for the crap modern e-mail is. Quoted comments (/* " .. " */) are
* taken almost verbatim from the algorithm.
*
* The entry point of this module is the `Threads` struct and its `new` method. It contains `ThreadNodes` which are the
* nodes in the thread trees that might have messages associated with them. The root nodes (first
* messages in each thread) are stored in `root_set` and `tree` vectors. The `ThreadTree` struct
* contains the sorted threads. `Threads` has inner mutability since we need to sort without the
* user having mutable ownership.
*/
use crate::mailbox::email::parser::BytesExt;
use crate::mailbox::email::*;
use uuid::Uuid;
use fnv::{FnvHashMap, FnvHashSet};
use std::cell::{Ref, RefCell};
use std::cmp;
use std::cmp::Ordering;
use std::fmt;
use std::iter::FromIterator;
use std::mem;
use std::ops::Index;
use std::result::Result as StdResult;
use std::str::FromStr;
type Envelopes = FnvHashMap<EnvelopeHash, Envelope>;
#[derive(PartialEq, Hash, Eq, Debug, Copy, Clone, Serialize, Deserialize, Default)]
pub struct ThreadHash(Uuid);
impl ThreadHash {
fn new() -> Self {
ThreadHash(Uuid::new_v4())
}
pub fn null() -> Self {
ThreadHash(Uuid::nil())
}
}
/* Helper macros to avoid repeating ourselves */
fn rec_change_root_parent(
b: &mut FnvHashMap<ThreadHash, ThreadNode>,
idx: ThreadHash,
ne