You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1658 lines
54KB

  1. /*
  2. * meli - mailbox threading module.
  3. *
  4. * Copyright 2017 Manos Pitsidianakis
  5. *
  6. * This file is part of meli.
  7. *
  8. * meli is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * meli is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with meli. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. /*!
  22. * This module implements Jamie Zawinski's (threading algorithm)
  23. * [https://www.jwz.org/doc/threading.html]. It is a bit of a beast, so prepare for a lot of
  24. * bloated code that's necessary for the crap modern e-mail is. Quoted comments (/* " .. " */) are
  25. * taken almost verbatim from the algorithm.
  26. *
  27. * The entry point of this module is the `Threads` struct and its `new` method. It contains `ThreadNodes` which are the
  28. * nodes in the thread trees that might have messages associated with them. The root nodes (first
  29. * messages in each thread) are stored in `root_set` and `tree` vectors. The `ThreadTree` struct
  30. * contains the sorted threads. `Threads` has inner mutability since we need to sort without the
  31. * user having mutable ownership.
  32. */
  33. use crate::email::parser::BytesExt;
  34. use crate::email::*;
  35. use crate::grapheme_clusters::*;
  36. use crate::structs::StackVec;
  37. use uuid::Uuid;
  38. use fnv::{FnvHashMap, FnvHashSet};
  39. use std::cell::{Ref, RefCell};
  40. use std::cmp;
  41. use std::cmp::Ordering;
  42. use std::fmt;
  43. use std::iter::FromIterator;
  44. use std::mem;
  45. use std::ops::Index;
  46. use std::result::Result as StdResult;
  47. use std::str::FromStr;
  48. use std::string::ToString;
  49. type Envelopes = FnvHashMap<EnvelopeHash, Envelope>;
  50. #[derive(PartialEq, Hash, Eq, Copy, Clone, Serialize, Deserialize, Default)]
  51. pub struct ThreadHash(Uuid);
  52. impl fmt::Debug for ThreadHash {
  53. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  54. write!(f, "{}", self.0.to_string())
  55. }
  56. }
  57. impl fmt::Display for ThreadHash {
  58. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  59. write!(f, "{}", self.0.to_string())
  60. }
  61. }
  62. impl ThreadHash {
  63. fn new() -> Self {
  64. ThreadHash(Uuid::new_v4())
  65. }
  66. pub fn null() -> Self {
  67. ThreadHash(Uuid::nil())
  68. }
  69. }
  70. /* Helper macros to avoid repeating ourselves */
  71. fn rec_change_root_parent(
  72. b: &mut FnvHashMap<ThreadHash, ThreadNode>,
  73. idx: ThreadHash,
  74. new_root: ThreadHash,
  75. ) {
  76. let parent = {
  77. let entry = b.entry(idx).or_default();
  78. entry.thread_group = new_root;
  79. entry.parent
  80. };
  81. if let Some(p) = parent {
  82. rec_change_children(b, p, new_root);
  83. rec_change_root_parent(b, p, new_root);
  84. }
  85. }
  86. fn rec_change_children(
  87. b: &mut FnvHashMap<ThreadHash, ThreadNode>,
  88. idx: ThreadHash,
  89. new_root: ThreadHash,
  90. ) {
  91. b.entry(idx).and_modify(|e| {
  92. e.thread_group = new_root;
  93. });
  94. let mut ctr = 0;
  95. while ctr < b[&idx].children.len() {
  96. let c = b[&idx].children[ctr];
  97. rec_change_children(b, c, new_root);
  98. ctr += 1;
  99. }
  100. }
  101. macro_rules! remove_from_parent {
  102. ($buf:expr, $idx:expr) => {{
  103. let mut parent: Option<ThreadHash> = None;
  104. let entry_parent = $buf.entry($idx).or_default().parent;
  105. if let Some(p) = entry_parent {
  106. parent = Some(p);
  107. if let Some(pos) = $buf[&p].children.iter().position(|c| *c == $idx) {
  108. $buf.entry(p).and_modify(|e| {
  109. e.children.remove(pos);
  110. });
  111. }
  112. rec_change_root_parent($buf, p, p);
  113. }
  114. $buf.entry($idx).and_modify(|e| e.parent = None);
  115. rec_change_children($buf, $idx, $idx);
  116. $buf.entry($idx).and_modify(|e| e.thread_group = $idx);
  117. parent
  118. }};
  119. }
  120. macro_rules! make {
  121. (($p:expr)parent of($c:expr), $buf:expr) => {{
  122. let prev_parent = remove_from_parent!($buf, $c);
  123. if !($buf[&$p]).children.contains(&$c) {
  124. /* Pruned nodes keep their children in case they show up in a later merge, so do not panic
  125. * if children exists */
  126. $buf.entry($p).and_modify(|e| e.children.push($c));
  127. }
  128. $buf.entry($c).and_modify(|e| e.parent = Some($p));
  129. union($buf, $c, $p);
  130. prev_parent
  131. }};
  132. }
  133. /* Strip common prefixes from subjects */
  134. trait SubjectPrefix {
  135. fn is_a_reply(&self) -> bool;
  136. fn strip_prefixes(&mut self);
  137. }
  138. impl SubjectPrefix for &[u8] {
  139. fn is_a_reply(&self) -> bool {
  140. self.starts_with(b"RE: ")
  141. || self.starts_with(b"Re: ")
  142. || self.starts_with(b"FW: ")
  143. || self.starts_with(b"Fw: ")
  144. }
  145. fn strip_prefixes(&mut self) {
  146. let result = {
  147. let mut slice = self.trim();
  148. loop {
  149. if slice.starts_with(b"RE: ")
  150. || slice.starts_with(b"Re: ")
  151. || slice.starts_with(b"FW: ")
  152. || slice.starts_with(b"Fw: ")
  153. {
  154. slice = &slice[3..];
  155. continue;
  156. }
  157. if slice.starts_with(b"FWD: ")
  158. || slice.starts_with(b"Fwd: ")
  159. || slice.starts_with(b"fwd: ")
  160. {
  161. slice = &slice[4..];
  162. continue;
  163. }
  164. if slice.starts_with(b" ") || slice.starts_with(b"\t") || slice.starts_with(b"\r") {
  165. //FIXME just trim whitespace
  166. slice = &slice[1..];
  167. continue;
  168. }
  169. if slice.starts_with(b"[")
  170. && !(slice.starts_with(b"[PATCH") || slice.starts_with(b"[RFC"))
  171. {
  172. if let Some(pos) = slice.find(b"]") {
  173. slice = &slice[pos..];
  174. continue;
  175. }
  176. slice = &slice[1..];
  177. continue;
  178. }
  179. break;
  180. }
  181. slice
  182. };
  183. *self = result;
  184. }
  185. }
  186. /* Sorting states. */
  187. #[derive(Debug, Clone, PartialEq, Copy, Deserialize, Serialize)]
  188. pub enum SortOrder {
  189. Asc,
  190. Desc,
  191. }
  192. #[derive(Debug, Clone, PartialEq, Copy, Deserialize, Serialize)]
  193. pub enum SortField {
  194. Subject,
  195. Date,
  196. }
  197. impl Default for SortField {
  198. fn default() -> Self {
  199. SortField::Date
  200. }
  201. }
  202. impl Default for SortOrder {
  203. fn default() -> Self {
  204. SortOrder::Desc
  205. }
  206. }
  207. impl FromStr for SortField {
  208. type Err = ();
  209. fn from_str(s: &str) -> StdResult<Self, Self::Err> {
  210. match s.trim() {
  211. "subject" | "s" | "sub" | "sbj" | "subj" => Ok(SortField::Subject),
  212. "date" | "d" => Ok(SortField::Date),
  213. _ => Err(()),
  214. }
  215. }
  216. }
  217. impl FromStr for SortOrder {
  218. type Err = ();
  219. fn from_str(s: &str) -> StdResult<Self, Self::Err> {
  220. match s.trim() {
  221. "asc" => Ok(SortOrder::Asc),
  222. "desc" => Ok(SortOrder::Desc),
  223. _ => Err(()),
  224. }
  225. }
  226. }
  227. /*
  228. * The thread tree holds the sorted state of the thread nodes */
  229. #[derive(Clone, Debug, Deserialize, Serialize)]
  230. struct ThreadTree {
  231. id: ThreadHash,
  232. children: Vec<ThreadTree>,
  233. }
  234. impl ThreadTree {
  235. fn new(id: ThreadHash) -> Self {
  236. ThreadTree {
  237. id,
  238. children: Vec::new(),
  239. }
  240. }
  241. fn insert_child(
  242. vec: &mut Vec<ThreadTree>,
  243. child: ThreadTree,
  244. sort: (SortField, SortOrder),
  245. buf: &FnvHashMap<ThreadHash, ThreadNode>,
  246. envelopes: &Envelopes,
  247. ) -> usize {
  248. let pos = match sort {
  249. (SortField::Date, SortOrder::Asc) => {
  250. match vec.binary_search_by(|probe| buf[&probe.id].date.cmp(&buf[&child.id].date)) {
  251. Ok(p) => p,
  252. Err(p) => p,
  253. }
  254. }
  255. (SortField::Date, SortOrder::Desc) => {
  256. match vec.binary_search_by(|probe| {
  257. buf[&probe.id].date.cmp(&buf[&child.id].date).reverse()
  258. }) {
  259. Ok(p) => p,
  260. Err(p) => p,
  261. }
  262. }
  263. (SortField::Subject, SortOrder::Asc) => {
  264. match vec.binary_search_by(|probe| {
  265. match (
  266. buf.get(&probe.id)
  267. .map(|n| n.message.as_ref())
  268. .unwrap_or(None),
  269. buf.get(&child.id)
  270. .map(|n| n.message.as_ref())
  271. .unwrap_or(None),
  272. ) {
  273. (Some(p), Some(c)) => envelopes[p]
  274. .subject()
  275. .split_graphemes()
  276. .cmp(&envelopes[c].subject().split_graphemes()),
  277. (Some(_), None) => Ordering::Greater,
  278. (None, Some(_)) => Ordering::Less,
  279. (None, None) => Ordering::Equal,
  280. }
  281. }) {
  282. Ok(p) => p,
  283. Err(p) => p,
  284. }
  285. }
  286. (SortField::Subject, SortOrder::Desc) => {
  287. match vec.binary_search_by(|probe| {
  288. match (
  289. buf.get(&probe.id)
  290. .map(|n| n.message.as_ref())
  291. .unwrap_or(None),
  292. buf.get(&child.id)
  293. .map(|n| n.message.as_ref())
  294. .unwrap_or(None),
  295. ) {
  296. (Some(p), Some(c)) => envelopes[c]
  297. .subject()
  298. .split_graphemes()
  299. .cmp(&envelopes[p].subject().split_graphemes()),
  300. (Some(_), None) => Ordering::Less,
  301. (None, Some(_)) => Ordering::Greater,
  302. (None, None) => Ordering::Equal,
  303. }
  304. }) {
  305. Ok(p) => p,
  306. Err(p) => p,
  307. }
  308. }
  309. };
  310. vec.insert(pos, child);
  311. pos
  312. }
  313. }
  314. /* `ThreadsIterator` returns messages according to the sorted order. For example, for the following
  315. * threads:
  316. *
  317. * ```
  318. * A_
  319. * |_ B
  320. * |_C
  321. * D
  322. * E_
  323. * |_F
  324. * ```
  325. *
  326. * the iterator returns them as `A, B, C, D, E, F`
  327. */
  328. pub struct ThreadsIterator<'a> {
  329. pos: usize,
  330. stack: StackVec<usize>,
  331. tree: Ref<'a, Vec<ThreadTree>>,
  332. }
  333. impl<'a> Iterator for ThreadsIterator<'a> {
  334. type Item = (usize, ThreadHash, bool);
  335. fn next(&mut self) -> Option<(usize, ThreadHash, bool)> {
  336. {
  337. let mut tree = &(*self.tree);
  338. for i in self.stack.iter() {
  339. tree = &tree[*i].children;
  340. }
  341. if self.pos == tree.len() {
  342. if let Some(p) = self.stack.pop() {
  343. self.pos = p + 1;
  344. } else {
  345. return None;
  346. }
  347. } else {
  348. debug_assert!(self.pos < tree.len());
  349. let ret = (
  350. self.stack.len(),
  351. tree[self.pos].id,
  352. !self.stack.is_empty() && (self.pos < (tree.len() - 1)),
  353. );
  354. if !tree[self.pos].children.is_empty() {
  355. self.stack.push(self.pos);
  356. self.pos = 0;
  357. return Some(ret);
  358. }
  359. self.pos += 1;
  360. return Some(ret);
  361. }
  362. }
  363. self.next()
  364. }
  365. }
  366. /* `ThreadIterator` returns messages of a specific thread according to the sorted order. For example, for the following
  367. * thread:
  368. *
  369. * ```
  370. * A_
  371. * |_ B
  372. * |_C
  373. * |_D
  374. * ```
  375. *
  376. * the iterator returns them as `A, B, C, D`
  377. */
  378. pub struct ThreadIterator<'a> {
  379. init_pos: usize,
  380. pos: usize,
  381. stack: StackVec<usize>,
  382. tree: Ref<'a, Vec<ThreadTree>>,
  383. }
  384. impl<'a> Iterator for ThreadIterator<'a> {
  385. type Item = (usize, ThreadHash);
  386. fn next(&mut self) -> Option<(usize, ThreadHash)> {
  387. {
  388. let mut tree = &(*self.tree);
  389. for i in self.stack.iter() {
  390. tree = &tree[*i].children;
  391. }
  392. if self.pos == tree.len() || (self.stack.is_empty() && self.pos > self.init_pos) {
  393. if self.stack.is_empty() {
  394. return None;
  395. }
  396. self.pos = self.stack.pop().unwrap() + 1;
  397. } else {
  398. debug_assert!(self.pos < tree.len());
  399. let ret = (self.stack.len(), tree[self.pos].id);
  400. if !tree[self.pos].children.is_empty() {
  401. self.stack.push(self.pos);
  402. self.pos = 0;
  403. return Some(ret);
  404. }
  405. self.pos += 1;
  406. return Some(ret);
  407. }
  408. }
  409. self.next()
  410. }
  411. }
  412. #[derive(Clone, Debug, Deserialize, Serialize)]
  413. pub struct ThreadNode {
  414. message: Option<EnvelopeHash>,
  415. parent: Option<ThreadHash>,
  416. children: Vec<ThreadHash>,
  417. date: UnixTimestamp,
  418. indentation: usize,
  419. show_subject: bool,
  420. pruned: bool,
  421. len: usize,
  422. has_unseen: bool,
  423. snoozed: bool,
  424. /* Union/Find set fields */
  425. thread_group: ThreadHash,
  426. rank: i32,
  427. }
  428. impl Default for ThreadNode {
  429. fn default() -> ThreadNode {
  430. ThreadNode {
  431. message: None,
  432. parent: None,
  433. children: Vec::new(),
  434. date: UnixTimestamp::default(),
  435. indentation: 0,
  436. show_subject: true,
  437. pruned: false,
  438. len: 0,
  439. has_unseen: false,
  440. snoozed: false,
  441. thread_group: ThreadHash::default(),
  442. rank: 0,
  443. }
  444. }
  445. }
  446. impl ThreadNode {
  447. fn new(thread_group: ThreadHash) -> Self {
  448. ThreadNode {
  449. thread_group,
  450. ..Default::default()
  451. }
  452. }
  453. pub fn show_subject(&self) -> bool {
  454. self.show_subject
  455. }
  456. pub fn has_unseen(&self) -> bool {
  457. self.has_unseen
  458. }
  459. pub fn len(&self) -> usize {
  460. self.len
  461. }
  462. pub fn is_empty(&self) -> bool {
  463. self.parent.is_none() && self.message.is_none() && self.children.is_empty()
  464. }
  465. pub fn message(&self) -> Option<EnvelopeHash> {
  466. self.message
  467. }
  468. pub fn has_message(&self) -> bool {
  469. self.message.is_some()
  470. }
  471. pub fn parent(&self) -> Option<ThreadHash> {
  472. self.parent
  473. }
  474. pub fn has_parent(&self) -> bool {
  475. self.parent.is_some()
  476. }
  477. pub fn children(&self) -> &[ThreadHash] {
  478. &self.children
  479. }
  480. pub fn indentation(&self) -> usize {
  481. self.indentation
  482. }
  483. pub fn snoozed(&self) -> bool {
  484. self.snoozed
  485. }
  486. pub fn thread_group(&self) -> ThreadHash {
  487. self.thread_group
  488. }
  489. pub fn set_snoozed(&mut self, set: bool) {
  490. self.snoozed = set;
  491. }
  492. }
  493. #[derive(Clone, Debug, Default, Deserialize, Serialize)]
  494. pub struct Threads {
  495. pub thread_nodes: FnvHashMap<ThreadHash, ThreadNode>,
  496. root_set: RefCell<Vec<ThreadHash>>,
  497. tree: RefCell<Vec<ThreadTree>>,
  498. message_ids: FnvHashMap<Vec<u8>, ThreadHash>,
  499. pub message_ids_set: FnvHashSet<Vec<u8>>,
  500. pub missing_message_ids: FnvHashSet<Vec<u8>>,
  501. pub hash_set: FnvHashSet<EnvelopeHash>,
  502. sort: RefCell<(SortField, SortOrder)>,
  503. subsort: RefCell<(SortField, SortOrder)>,
  504. }
  505. impl PartialEq for ThreadNode {
  506. fn eq(&self, other: &ThreadNode) -> bool {
  507. match (self.message, other.message) {
  508. (Some(s), Some(o)) => s == o,
  509. _ => false,
  510. }
  511. }
  512. }
  513. pub struct RootIterator<'a> {
  514. pos: usize,
  515. root_tree: Ref<'a, Vec<ThreadTree>>,
  516. }
  517. impl<'a> Iterator for RootIterator<'a> {
  518. type Item = ThreadHash;
  519. fn next(&mut self) -> Option<ThreadHash> {
  520. {
  521. if self.pos == self.root_tree.len() {
  522. return None;
  523. }
  524. self.pos += 1;
  525. Some(self.root_tree[self.pos - 1].id)
  526. }
  527. }
  528. }
  529. fn find_ref(buf: &FnvHashMap<ThreadHash, ThreadNode>, h: ThreadHash) -> ThreadHash {
  530. if buf[&h].thread_group == h {
  531. return h;
  532. }
  533. let p = buf[&h].thread_group;
  534. find_ref(buf, p)
  535. }
  536. fn find(buf: &mut FnvHashMap<ThreadHash, ThreadNode>, h: ThreadHash) -> ThreadHash {
  537. if buf[&h].thread_group == h {
  538. return h;
  539. }
  540. let p = buf[&h].thread_group;
  541. let new_group = find(buf, p);
  542. buf.entry(h).and_modify(|e| e.thread_group = new_group);
  543. new_group
  544. }
  545. fn union(buf: &mut FnvHashMap<ThreadHash, ThreadNode>, x: ThreadHash, y: ThreadHash) -> ThreadHash {
  546. let mut x_root = find(buf, x);
  547. let mut y_root = find(buf, y);
  548. // x and y are already in the same set
  549. if x_root == y_root {
  550. return x_root;
  551. }
  552. if buf[&x_root].rank < buf[&y_root].rank {
  553. mem::swap(&mut x_root, &mut y_root);
  554. }
  555. // x and y are not in same set, so we merge them
  556. //
  557. buf.entry(y_root).and_modify(|e| e.thread_group = x_root);
  558. if buf[&x_root].rank == buf[&y_root].rank {
  559. buf.entry(x_root).and_modify(|e| {
  560. e.rank += 1;
  561. });
  562. }
  563. x_root
  564. }
  565. impl Threads {
  566. pub fn is_snoozed(&self, h: ThreadHash) -> bool {
  567. let root = find_ref(&self.thread_nodes, h);
  568. self.thread_nodes[&root].snoozed()
  569. }
  570. pub fn find(&mut self, i: ThreadHash) -> ThreadHash {
  571. find(&mut self.thread_nodes, i)
  572. }
  573. fn union(&mut self, x: ThreadHash, y: ThreadHash) -> ThreadHash {
  574. let mut x_root = self.find(x);
  575. let mut y_root = self.find(y);
  576. // x and y are already in the same set
  577. if x_root == y_root {
  578. return x_root;
  579. }
  580. if self.thread_nodes[&x_root].rank < self.thread_nodes[&y_root].rank {
  581. mem::swap(&mut x_root, &mut y_root);
  582. }
  583. // x and y are not in same set, so we merge them
  584. //
  585. self.thread_nodes
  586. .entry(y_root)
  587. .and_modify(|e| e.thread_group = x_root);
  588. if self.thread_nodes[&x_root].rank == self.thread_nodes[&y_root].rank {
  589. self.thread_nodes.entry(x_root).and_modify(|e| e.rank += 1);
  590. }
  591. x_root
  592. }
  593. fn prune_empty_nodes(&mut self, root_set: &mut Vec<ThreadHash>) {
  594. fn prune(
  595. thread_nodes: &mut FnvHashMap<ThreadHash, ThreadNode>,
  596. idx: ThreadHash,
  597. root_set: &mut Vec<ThreadHash>,
  598. ) -> bool {
  599. /* "If it is an empty container with no children, nuke it." */
  600. if !thread_nodes[&idx].has_message() && thread_nodes[&idx].children.is_empty() {
  601. remove_from_parent!(thread_nodes, idx);
  602. thread_nodes.entry(idx).and_modify(|n| n.pruned = true);
  603. return true;
  604. }
  605. /*
  606. if !thread_nodes[&idx].has_message() && !thread_nodes[&idx].has_parent() {
  607. if thread_nodes[&idx].children.len() == 1 {
  608. /* "Do not promote the children if doing so would promote them to the root set
  609. * -- unless there is only one child, in which case, do." */
  610. let child = thread_nodes[&idx].children[0];
  611. root_set.push(child);
  612. remove_from_parent!(thread_nodes, child);
  613. thread_nodes.entry(idx).and_modify(|n| {
  614. n.pruned = true;
  615. n.children.push(child);
  616. });
  617. return true; // Pruned
  618. }
  619. } else if let Some(p) = thread_nodes[&idx].parent {
  620. if !thread_nodes[&idx].has_message() {
  621. let orphans = thread_nodes[&idx].children.clone();
  622. for c in &orphans {
  623. make!((p) parent of (*c), thread_nodes);
  624. }
  625. remove_from_parent!(thread_nodes, idx);
  626. /* Keep children in case we happen upon them later and mark it as pruned */
  627. thread_nodes.entry(idx).and_modify(|n| {
  628. n.pruned = true;
  629. n.children = orphans;
  630. });
  631. return true; // Pruned
  632. }
  633. }
  634. */
  635. /* Recurse to children, but keep in mind more children can be added in each iteration
  636. */
  637. let mut c_idx = 0;
  638. loop {
  639. if c_idx >= thread_nodes[&idx].children.len() {
  640. break;
  641. }
  642. let c = thread_nodes[&idx].children[c_idx];
  643. if !prune(thread_nodes, c, root_set) {
  644. c_idx += 1;
  645. }
  646. }
  647. thread_nodes[&idx].pruned
  648. }
  649. let mut idx = 0;
  650. loop {
  651. if idx >= root_set.len() {
  652. break;
  653. }
  654. if prune(&mut self.thread_nodes, root_set[idx], root_set) {
  655. root_set.remove(idx);
  656. } else {
  657. idx += 1;
  658. }
  659. }
  660. }
  661. pub fn prune_tree(&self) {
  662. self.tree
  663. .borrow_mut()
  664. .retain(|c| !self.thread_nodes[&c.id].is_empty());
  665. }
  666. pub fn new(envelopes: &mut Envelopes) -> Threads {
  667. /* To reconstruct thread information from the mails we need: */
  668. /* a vector to hold thread members */
  669. let thread_nodes: FnvHashMap<ThreadHash, ThreadNode> = FnvHashMap::with_capacity_and_hasher(
  670. (envelopes.len() as f64 * 1.2) as usize,
  671. Default::default(),
  672. );
  673. /* A hash table of Message IDs */
  674. let message_ids: FnvHashMap<Vec<u8>, ThreadHash> =
  675. FnvHashMap::with_capacity_and_hasher(envelopes.len(), Default::default());
  676. /* A hash set of Message IDs we haven't encountered yet as an Envelope */
  677. let missing_message_ids: FnvHashSet<Vec<u8>> =
  678. FnvHashSet::with_capacity_and_hasher(envelopes.len(), Default::default());
  679. /* A hash set of Message IDs we have encountered as a MessageID */
  680. let message_ids_set: FnvHashSet<Vec<u8>> =
  681. FnvHashSet::with_capacity_and_hasher(envelopes.len(), Default::default());
  682. let hash_set: FnvHashSet<EnvelopeHash> =
  683. FnvHashSet::with_capacity_and_hasher(envelopes.len(), Default::default());
  684. let mut t = Threads {
  685. thread_nodes,
  686. message_ids,
  687. message_ids_set,
  688. missing_message_ids,
  689. hash_set,
  690. subsort: RefCell::new((SortField::Subject, SortOrder::Desc)),
  691. ..Default::default()
  692. };
  693. /* Add each message to message_ids and threads, and link them together according to the
  694. * References / In-Reply-To headers */
  695. t.link_threads(envelopes);
  696. t.create_root_set(envelopes);
  697. t.build_envelopes(envelopes);
  698. //for (i, _t) in t.thread_nodes.iter().enumerate() {
  699. // if !_t.has_parent() && _t.children.is_empty() && !_t.has_message() {
  700. // continue;
  701. // }
  702. // debug!("--------------------------");
  703. // if let Some(m) = _t.message {
  704. // debug!(
  705. // "\tmessage: {}\t{}",
  706. // envelopes[&m].subject(),
  707. // envelopes[&m].message_id()
  708. // );
  709. // } else {
  710. // debug!("\tNo message");
  711. // }
  712. // debug!(
  713. // "Thread #{}, children {}:\n\t{:#?}",
  714. // i,
  715. // _t.children.len(),
  716. // _t
  717. // );
  718. // if !_t.children.is_empty() {
  719. // debug!("{:?}", _t.children);
  720. // }
  721. //}
  722. //for (i, _t) in t.tree.borrow().iter().enumerate() {
  723. // debug!("Tree #{} id {}, children {}", i, _t.id, _t.children.len());
  724. // if let Some(m) = t.thread_nodes[_t.id].message {
  725. // debug!("\tmessage: {}", envelopes[&m].subject());
  726. // } else {
  727. // debug!("\tNo message");
  728. // }
  729. //}
  730. t
  731. }
  732. fn create_root_set(&mut self, envelopes: &Envelopes) {
  733. /* Walk over the elements of message_ids, and gather a list of the ThreadNode objects that
  734. * have no parents. These are the root messages of each thread */
  735. let mut root_set: Vec<ThreadHash> = Vec::with_capacity(envelopes.len());
  736. /* Find the root set */
  737. for v in self.message_ids.values() {
  738. if self.thread_nodes[v].parent.is_none() {
  739. root_set.push(*v);
  740. }
  741. }
  742. /* Prune empty thread nodes */
  743. self.prune_empty_nodes(&mut root_set);
  744. self.root_set = RefCell::new(root_set);
  745. }
  746. pub fn print_tree(&self, envelopes: &Envelopes) {
  747. let len = self.tree.borrow().len();
  748. for (i, t) in self.tree.borrow().iter().enumerate() {
  749. debug!("tree #{}/{}", i + 1, len);
  750. print_threadnodes(t.id, &self.thread_nodes, envelopes);
  751. }
  752. }
  753. pub fn threads_iter(&self) -> ThreadsIterator {
  754. ThreadsIterator {
  755. pos: 0,
  756. stack: StackVec::new(),
  757. tree: self.tree.borrow(),
  758. }
  759. }
  760. pub fn thread_iter(&self, index: usize) -> ThreadIterator {
  761. ThreadIterator {
  762. init_pos: index,
  763. pos: index,
  764. stack: StackVec::new(),
  765. tree: self.tree.borrow(),
  766. }
  767. }
  768. pub fn update_envelope(
  769. &mut self,
  770. old_hash: EnvelopeHash,
  771. new_hash: EnvelopeHash,
  772. envelopes: &Envelopes,
  773. ) -> Result<(), ()> {
  774. /* must update:
  775. * - hash_set
  776. * - message fields in thread_nodes
  777. */
  778. let thread_hash = if let Some((key, node)) = self
  779. .thread_nodes
  780. .iter_mut()
  781. .find(|(_, n)| n.message.map(|n| n == old_hash).unwrap_or(false))
  782. {
  783. node.message = Some(new_hash);
  784. *key
  785. } else {
  786. return Err(());
  787. };
  788. self.hash_set.remove(&old_hash);
  789. self.hash_set.insert(new_hash);
  790. self.rebuild_thread(thread_hash, envelopes);
  791. Ok(())
  792. }
  793. #[inline]
  794. pub fn remove(&mut self, envelope_hash: EnvelopeHash, envelopes: &mut Envelopes) {
  795. self.hash_set.remove(&envelope_hash);
  796. //{
  797. // let pos = self
  798. // .thread_nodes
  799. // .iter()
  800. // .position(|n| n.message.map(|n| n == envelope_hash).unwrap_or(false))
  801. // .unwrap();
  802. // debug!("DEBUG: {} in threads is idx= {}", envelope_hash, pos);
  803. //}
  804. let t_id: ThreadHash;
  805. {
  806. if let Some((pos, n)) = self
  807. .thread_nodes
  808. .iter_mut()
  809. .find(|(_, n)| n.message.map(|n| n == envelope_hash).unwrap_or(false))
  810. {
  811. t_id = *pos;
  812. n.message = None;
  813. } else {
  814. /* else it was deleted during a thread_rebuild or others */
  815. return;
  816. }
  817. }
  818. let mut node_idx = t_id;
  819. /* Trace path back to root ThreadNode */
  820. while let Some(p) = &self.thread_nodes[&node_idx].parent {
  821. node_idx = *p;
  822. }
  823. {
  824. let tree = self.tree.get_mut();
  825. if let Some(pos) = tree.iter().position(|t| t.id == node_idx) {
  826. tree[pos].children.clear();
  827. if node_idx == t_id {
  828. tree.remove(pos);
  829. } else {
  830. node_build(
  831. &mut tree[pos],
  832. node_idx,
  833. *(self.sort.borrow()),
  834. &mut self.thread_nodes,
  835. 1,
  836. envelopes,
  837. );
  838. }
  839. }
  840. }
  841. let mut root_set: Vec<ThreadHash> = self.tree.borrow().iter().map(|t| t.id).collect();
  842. self.prune_empty_nodes(&mut root_set);
  843. self.tree.borrow_mut().retain(|t| root_set.contains(&t.id));
  844. }
  845. pub fn amend(&mut self, envelopes: &mut Envelopes) {
  846. let new_hash_set = FnvHashSet::from_iter(envelopes.keys().cloned());
  847. let difference: Vec<EnvelopeHash> =
  848. self.hash_set.difference(&new_hash_set).cloned().collect();
  849. for h in difference {
  850. self.remove(h, envelopes);
  851. }
  852. let difference: Vec<EnvelopeHash> =
  853. new_hash_set.difference(&self.hash_set).cloned().collect();
  854. for h in difference {
  855. debug!("inserting {}", envelopes[&h].subject());
  856. let env = envelopes.entry(h).or_default() as *mut Envelope;
  857. unsafe {
  858. // `envelopes` is borrowed immutably and `insert` only changes the envelope's
  859. // `thread` field.
  860. self.insert(&mut (*env), envelopes);
  861. }
  862. }
  863. self.create_root_set(envelopes);
  864. let mut root_set: Vec<ThreadHash> = self.tree.borrow().iter().map(|t| t.id).collect();
  865. self.prune_empty_nodes(&mut root_set);
  866. let tree = self.tree.get_mut();
  867. tree.retain(|t| root_set.contains(&t.id));
  868. }
  869. pub fn insert(&mut self, envelope: &mut Envelope, envelopes: &Envelopes) {
  870. self.link_envelope(envelope);
  871. {
  872. let id = self.message_ids[envelope.message_id().raw()];
  873. self.rebuild_thread(id, envelopes);
  874. }
  875. }
  876. /* Insert or update */
  877. pub fn insert_reply(&mut self, envelopes: &mut Envelopes, env_hash: EnvelopeHash) -> bool {
  878. let reply_to_id: Option<ThreadHash> = self
  879. .message_ids
  880. .get(
  881. envelopes[&env_hash]
  882. .in_reply_to()
  883. .map(crate::email::StrBuild::raw)
  884. .unwrap_or(&[]),
  885. )
  886. .cloned();
  887. if let Some(id) = self
  888. .message_ids
  889. .get(envelopes[&env_hash].message_id().raw())
  890. .cloned()
  891. {
  892. self.thread_nodes.entry(id).and_modify(|n| {
  893. n.message = Some(env_hash);
  894. n.date = envelopes[&env_hash].date();
  895. n.pruned = false;
  896. if n.parent.is_none() {
  897. if let Some(reply_to_id) = reply_to_id {
  898. n.parent = Some(reply_to_id);
  899. }
  900. }
  901. });
  902. if let Some(reply_to_id) = reply_to_id {
  903. if !self.thread_nodes[&reply_to_id].children.contains(&id) {
  904. make!((reply_to_id) parent of (id), &mut self.thread_nodes);
  905. self.union(id, reply_to_id);
  906. }
  907. }
  908. self.rebuild_thread(reply_to_id.unwrap_or(id), envelopes);
  909. self.message_ids
  910. .insert(envelopes[&env_hash].message_id().raw().to_vec(), id);
  911. self.message_ids_set
  912. .insert(envelopes[&env_hash].message_id().raw().to_vec().to_vec());
  913. self.missing_message_ids
  914. .remove(envelopes[&env_hash].message_id().raw());
  915. envelopes.get_mut(&env_hash).unwrap().set_thread(id);
  916. self.hash_set.insert(env_hash);
  917. true
  918. } else if let Some(reply_to_id) = reply_to_id {
  919. let new_id = ThreadHash::new();
  920. self.thread_nodes.insert(
  921. new_id,
  922. ThreadNode {
  923. message: Some(env_hash),
  924. parent: Some(reply_to_id),
  925. date: envelopes[&env_hash].date(),
  926. ..ThreadNode::new(new_id)
  927. },
  928. );
  929. self.message_ids
  930. .insert(envelopes[&env_hash].message_id().raw().to_vec(), new_id);
  931. self.message_ids_set
  932. .insert(envelopes[&env_hash].message_id().raw().to_vec().to_vec());
  933. self.missing_message_ids
  934. .remove(envelopes[&env_hash].message_id().raw());
  935. envelopes.get_mut(&env_hash).unwrap().set_thread(new_id);
  936. self.hash_set.insert(env_hash);
  937. self.union(reply_to_id, new_id);
  938. make!((reply_to_id) parent of (new_id), &mut self.thread_nodes);
  939. self.rebuild_thread(reply_to_id, envelopes);
  940. true
  941. } else {
  942. false
  943. }
  944. /*
  945. {
  946. if let Some(in_reply_to) = envelope.in_reply_to() {
  947. if !self.message_ids.contains_key(in_reply_to.raw()) {
  948. return false;
  949. }
  950. } else {
  951. return false;
  952. }
  953. }
  954. let hash: EnvelopeHash = envelope.hash();
  955. envelopes.insert(hash, envelope.clone());
  956. {
  957. let envelope = envelopes.entry(hash).or_default() as *mut Envelope;
  958. unsafe {
  959. /* Safe because insert only changes envelope's fields and nothing more */
  960. self.insert(&mut (*envelope), &envelopes);
  961. }
  962. }
  963. let envelope: &Envelope = &envelopes[&hash];
  964. {
  965. let in_reply_to = envelope.in_reply_to().unwrap().raw();
  966. let parent_id = self.message_ids[in_reply_to];
  967. self.rebuild_thread(parent_id, envelopes);
  968. }
  969. true
  970. */
  971. }
  972. /* Update thread tree information on envelope insertion */
  973. fn rebuild_thread(&mut self, id: ThreadHash, envelopes: &Envelopes) {
  974. let mut node_idx = id;
  975. let mut stack = StackVec::new();
  976. {
  977. let tree = self.tree.get_mut();
  978. for &c in &self.thread_nodes[&id].children {
  979. if let Some(pos) = tree.iter().position(|t| t.id == c) {
  980. tree.remove(pos);
  981. }
  982. }
  983. }
  984. let no_parent: bool = if let Some(node) = self.thread_nodes.get(&node_idx) {
  985. if let (None, None, 0) = (node.parent, node.message, node.children.len()) {
  986. return;
  987. }
  988. node.parent.is_none()
  989. } else {
  990. panic!(format!(
  991. "node_idx = {:?} not found in self.thread_nodes",
  992. node_idx
  993. ));
  994. };
  995. if no_parent {
  996. let tree = self.tree.get_mut();
  997. if let Some(pos) = tree.iter().position(|t| t.id == id) {
  998. tree[pos] = ThreadTree::new(id);
  999. node_build(
  1000. &mut tree[pos],
  1001. id,
  1002. *(self.sort.borrow()),
  1003. &mut self.thread_nodes,
  1004. 1,
  1005. envelopes,
  1006. );
  1007. return;
  1008. } else {
  1009. for &c in &self.thread_nodes[&id].children {
  1010. if let Some(pos) = tree.iter().position(|t| t.id == c) {
  1011. tree.remove(pos);
  1012. }
  1013. }
  1014. }
  1015. let mut new_tree = ThreadTree::new(id);
  1016. node_build(
  1017. &mut new_tree,
  1018. id,
  1019. *(self.sort.borrow()),
  1020. &mut self.thread_nodes,
  1021. 1,
  1022. envelopes,
  1023. );
  1024. ThreadTree::insert_child(
  1025. tree,
  1026. new_tree,
  1027. *(self.sort.borrow()),
  1028. &self.thread_nodes,
  1029. envelopes,
  1030. );
  1031. return;
  1032. }
  1033. /* Trace path back to root ThreadNode */
  1034. while let Some(p) = &self.thread_nodes[&node_idx].parent {
  1035. node_idx = *p;
  1036. stack.push(node_idx);
  1037. }
  1038. {
  1039. /* Trace path from root ThreadTree to the envelope's parent */
  1040. let mut tree = self.tree.get_mut();
  1041. for &s in stack.iter().rev() {
  1042. /* Borrow checker is being a tad silly here, so the following
  1043. * is basically this:
  1044. *
  1045. * let tree = &mut tree[s].children;
  1046. */
  1047. let temp_tree = tree;
  1048. if let Some(pos) = temp_tree.iter().position(|v| v.id == s) {
  1049. tree = &mut temp_tree[pos].children;
  1050. } else {
  1051. let mut tree_node = ThreadTree::new(s);
  1052. node_build(
  1053. &mut tree_node,
  1054. s,
  1055. *(self.sort.borrow()),
  1056. &mut self.thread_nodes,
  1057. 1,
  1058. envelopes,
  1059. );
  1060. let new_id = ThreadTree::insert_child(
  1061. temp_tree,
  1062. tree_node,
  1063. *(self.sort.borrow()),
  1064. &self.thread_nodes,
  1065. envelopes,
  1066. );
  1067. tree = &mut temp_tree[new_id].children;
  1068. }
  1069. }
  1070. let pos = if let Some(pos) = tree.iter().position(|v| v.id == id) {
  1071. pos
  1072. } else {
  1073. /* Add new child */
  1074. let tree_node = ThreadTree::new(id);
  1075. ThreadTree::insert_child(
  1076. tree,
  1077. tree_node,
  1078. *(self.sort.borrow()),
  1079. &self.thread_nodes,
  1080. envelopes,
  1081. )
  1082. };
  1083. node_build(
  1084. &mut tree[pos],
  1085. id,
  1086. *(self.sort.borrow()),
  1087. &mut self.thread_nodes,
  1088. 1,
  1089. envelopes,
  1090. );
  1091. }
  1092. }
  1093. /*
  1094. * Finalize instance by building the thread tree, set show subject and thread lengths etc. */
  1095. fn build_envelopes(&mut self, envelopes: &Envelopes) {
  1096. {
  1097. let tree = self.tree.get_mut();
  1098. tree.clear();
  1099. for i in self.root_set.borrow().iter() {
  1100. let mut tree_node = ThreadTree::new(*i);
  1101. node_build(
  1102. &mut tree_node,
  1103. *i,
  1104. *(self.sort.borrow()),
  1105. &mut self.thread_nodes,
  1106. 0, /* indentation */
  1107. envelopes,
  1108. );
  1109. ThreadTree::insert_child(
  1110. tree,
  1111. tree_node,
  1112. *(self.sort.borrow()),
  1113. &self.thread_nodes,
  1114. envelopes,
  1115. );
  1116. }
  1117. }
  1118. self.inner_sort_by(*self.sort.borrow(), envelopes);
  1119. self.inner_subsort_by(*self.subsort.borrow(), envelopes);
  1120. }
  1121. fn inner_subsort_by(&self, subsort: (SortField, SortOrder), envelopes: &Envelopes) {
  1122. let tree = &mut self.tree.borrow_mut();
  1123. for t in tree.iter_mut() {
  1124. t.children.sort_by(|a, b| match subsort {
  1125. (SortField::Date, SortOrder::Desc) => {
  1126. let a = &self.thread_nodes[&a.id];
  1127. let b = &self.thread_nodes[&b.id];
  1128. b.date.cmp(&a.date)
  1129. }
  1130. (SortField::Date, SortOrder::Asc) => {
  1131. let a = &self.thread_nodes[&a.id];
  1132. let b = &self.thread_nodes[&b.id];
  1133. a.date.cmp(&b.date)
  1134. }
  1135. (SortField::Subject, SortOrder::Desc) => {
  1136. let a = &self.thread_nodes[&a.id].message();
  1137. let b = &self.thread_nodes[&b.id].message();
  1138. match (a, b) {
  1139. (Some(_), Some(_)) => {}
  1140. (Some(_), None) => {
  1141. return Ordering::Greater;
  1142. }
  1143. (None, Some(_)) => {
  1144. return Ordering::Less;
  1145. }
  1146. (None, None) => {
  1147. return Ordering::Equal;
  1148. }
  1149. }
  1150. let ma = &envelopes[&a.unwrap()];
  1151. let mb = &envelopes[&b.unwrap()];
  1152. ma.subject().cmp(&mb.subject())
  1153. }
  1154. (SortField::Subject, SortOrder::Asc) => {
  1155. let a = &self.thread_nodes[&a.id].message();
  1156. let b = &self.thread_nodes[&b.id].message();
  1157. match (a, b) {
  1158. (Some(_), Some(_)) => {}
  1159. (Some(_), None) => {
  1160. return Ordering::Less;
  1161. }
  1162. (None, Some(_)) => {
  1163. return Ordering::Greater;
  1164. }
  1165. (None, None) => {
  1166. return Ordering::Equal;
  1167. }
  1168. }
  1169. let ma = &envelopes[&a.unwrap()];
  1170. let mb = &envelopes[&b.unwrap()];
  1171. mb.subject().cmp(&ma.subject())
  1172. }
  1173. });
  1174. }
  1175. }
  1176. fn inner_sort_by(&self, sort: (SortField, SortOrder), envelopes: &Envelopes) {
  1177. let tree = &mut self.tree.borrow_mut();
  1178. tree.sort_by(|a, b| match sort {
  1179. (SortField::Date, SortOrder::Desc) => {
  1180. let a = &self.thread_nodes[&a.id];
  1181. let b = &self.thread_nodes[&b.id];
  1182. b.date.cmp(&a.date)
  1183. }
  1184. (SortField::Date, SortOrder::Asc) => {
  1185. let a = &self.thread_nodes[&a.id];
  1186. let b = &self.thread_nodes[&b.id];
  1187. a.date.cmp(&b.date)
  1188. }
  1189. (SortField::Subject, SortOrder::Desc) => {
  1190. let a = &self.thread_nodes[&a.id].message();
  1191. let b = &self.thread_nodes[&b.id].message();
  1192. match (a, b) {
  1193. (Some(_), Some(_)) => {}
  1194. (Some(_), None) => {
  1195. return Ordering::Greater;
  1196. }
  1197. (None, Some(_)) => {
  1198. return Ordering::Less;
  1199. }
  1200. (None, None) => {
  1201. return Ordering::Equal;
  1202. }
  1203. }
  1204. let ma = &envelopes[&a.unwrap()];
  1205. let mb = &envelopes[&b.unwrap()];
  1206. ma.subject()
  1207. .split_graphemes()
  1208. .cmp(&mb.subject().split_graphemes())
  1209. }
  1210. (SortField::Subject, SortOrder::Asc) => {
  1211. let a = &self.thread_nodes[&a.id].message();
  1212. let b = &self.thread_nodes[&b.id].message();
  1213. match (a, b) {
  1214. (Some(_), Some(_)) => {}
  1215. (Some(_), None) => {
  1216. return Ordering::Less;
  1217. }
  1218. (None, Some(_)) => {
  1219. return Ordering::Greater;
  1220. }
  1221. (None, None) => {
  1222. return Ordering::Equal;
  1223. }
  1224. }
  1225. let ma = &envelopes[&a.unwrap()];
  1226. let mb = &envelopes[&b.unwrap()];
  1227. mb.subject()
  1228. .as_ref()
  1229. .split_graphemes()
  1230. .cmp(&ma.subject().split_graphemes())
  1231. }
  1232. });
  1233. }
  1234. pub fn sort_by(
  1235. &self,
  1236. sort: (SortField, SortOrder),
  1237. subsort: (SortField, SortOrder),
  1238. envelopes: &Envelopes,
  1239. ) {
  1240. if *self.sort.borrow() != sort {
  1241. self.inner_sort_by(sort, envelopes);
  1242. *self.sort.borrow_mut() = sort;
  1243. }
  1244. if *self.subsort.borrow() != subsort {
  1245. self.inner_subsort_by(subsort, envelopes);
  1246. *self.subsort.borrow_mut() = subsort;
  1247. }
  1248. }
  1249. pub fn thread_to_mail(&self, i: ThreadHash) -> EnvelopeHash {
  1250. let thread = &self.thread_nodes[&i];
  1251. thread.message().unwrap()
  1252. }
  1253. pub fn thread_nodes(&self) -> &FnvHashMap<ThreadHash, ThreadNode> {
  1254. &self.thread_nodes
  1255. }
  1256. pub fn len(&self) -> usize {
  1257. self.hash_set.len()
  1258. }
  1259. pub fn root_len(&self) -> usize {
  1260. self.tree.borrow().len()
  1261. }
  1262. pub fn root_set(&self, idx: usize) -> ThreadHash {
  1263. self.tree.borrow()[idx].id
  1264. }
  1265. pub fn root_iter(&self) -> RootIterator {
  1266. self.prune_tree();
  1267. RootIterator {
  1268. pos: 0,
  1269. root_tree: self.tree.borrow(),
  1270. }
  1271. }
  1272. pub fn has_sibling(&self, h: ThreadHash) -> bool {
  1273. if let Some(parent) = self[&h].parent {
  1274. let children = &self[&parent].children;
  1275. if children.is_empty() {
  1276. return false;
  1277. }
  1278. let pos = children
  1279. .iter()
  1280. .position(|&x| x == h)
  1281. .expect("Did not find node in parent!");
  1282. pos != children.len() - 1
  1283. } else {
  1284. false
  1285. }
  1286. }
  1287. fn link_envelope(&mut self, envelope: &mut Envelope) {
  1288. let t_idx: ThreadHash = {
  1289. let m_id = envelope.message_id().raw();
  1290. /* t_idx: The index of this message's ThreadNode in thread_nodes
  1291. *
  1292. * If id_table contains an empty Container for this ID:
  1293. * Store this message in the Container's message slot.
  1294. * Else:
  1295. * Create a new Container object holding this message;
  1296. * Index the Container by Message-ID in id_table.
  1297. */
  1298. if self.message_ids.get(m_id).is_some() {
  1299. let node_idx = self.message_ids[m_id];
  1300. /* the already existing ThreadNote should be empty, since we're
  1301. * seeing this message for the first time. otherwise it's a
  1302. * duplicate. */
  1303. if !self.missing_message_ids.contains(m_id) {
  1304. return;
  1305. }
  1306. self.missing_message_ids.remove(m_id);
  1307. node_idx
  1308. } else {
  1309. /* Create a new ThreadNode object holding this message */
  1310. /* The new thread node's set is just itself */
  1311. let new_id = ThreadHash::new();
  1312. let node = ThreadNode {
  1313. message: Some(envelope.hash()),
  1314. date: envelope.date(),
  1315. thread_group: new_id,
  1316. ..Default::default()
  1317. };
  1318. self.thread_nodes.insert(new_id, node);
  1319. self.message_ids.insert(m_id.to_vec(), new_id);
  1320. self.message_ids_set.insert(m_id.to_vec());
  1321. new_id
  1322. }
  1323. };
  1324. self.thread_nodes.entry(t_idx).and_modify(|e| {
  1325. e.date = envelope.date();
  1326. e.message = Some(envelope.hash());
  1327. e.has_unseen |= !envelope.is_seen();
  1328. });
  1329. envelope.set_thread(t_idx);
  1330. self.hash_set.insert(envelope.hash());
  1331. /* For each element in the message's References field:
  1332. *
  1333. * Find a ThreadNode object for the given Message-ID:
  1334. * If there's one in message_ids use that;
  1335. * Otherwise, make (and index) one with a null Message
  1336. *
  1337. * Link the References field's ThreadNode together in the order implied
  1338. * by the References header.
  1339. */
  1340. /* The index of the reference we are currently examining, start from current message */
  1341. let mut ref_ptr = t_idx;
  1342. for &refn in envelope.references().iter().rev() {
  1343. let r_id = refn.raw();
  1344. let parent_id = if self.message_ids.contains_key(r_id) {
  1345. self.message_ids[r_id]
  1346. } else {
  1347. /* Create a new ThreadNode object holding this reference */
  1348. let new_id = ThreadHash::new();
  1349. self.thread_nodes.insert(
  1350. new_id,
  1351. ThreadNode {
  1352. date: envelope.date(),
  1353. thread_group: new_id,
  1354. ..Default::default()
  1355. },
  1356. );
  1357. self.message_ids.insert(r_id.to_vec(), new_id);
  1358. self.missing_message_ids.insert(r_id.to_vec());
  1359. self.message_ids_set.insert(r_id.to_vec());
  1360. new_id
  1361. };
  1362. /* If they are already linked, don't change the existing links.
  1363. if self.thread_nodes[&ref_ptr].has_parent()
  1364. && self.thread_nodes[&ref_ptr].parent.unwrap() != parent_id
  1365. {
  1366. ref_ptr = parent_id;
  1367. continue;
  1368. } */
  1369. if self.thread_nodes[&ref_ptr].parent.is_some() {
  1370. if self.thread_nodes[&parent_id].parent == Some(ref_ptr) {
  1371. eprintln!("ALARM");
  1372. remove_from_parent!(&mut self.thread_nodes, parent_id);
  1373. }
  1374. ref_ptr = parent_id;
  1375. continue;
  1376. }
  1377. /* Do not add a link if adding that link would introduce a loop: that is, before
  1378. * asserting A->B, search down the children of B to see if A is reachable, and also
  1379. * search down the children of A to see if B is reachable. If either is already
  1380. * reachable as a child of the other, don't add the link.
  1381. */
  1382. if self.find(ref_ptr) != self.find(parent_id) {
  1383. self.union(ref_ptr, parent_id);
  1384. make!((parent_id) parent of (ref_ptr), &mut self.thread_nodes);
  1385. }
  1386. ref_ptr = parent_id;
  1387. }
  1388. let mut tree = self.tree.borrow_mut();
  1389. let mut i = 0;
  1390. while i < tree.len() {
  1391. // Evaluate if useless
  1392. let node = &self.thread_nodes[&tree[i].id];
  1393. if let (None, None, 0) = (node.parent, node.message, node.children.len()) {
  1394. tree.remove(i);
  1395. continue;
  1396. }
  1397. i += 1;
  1398. }
  1399. }
  1400. fn link_threads(&mut self, envelopes: &mut Envelopes) {
  1401. for e in envelopes.values_mut() {
  1402. self.link_envelope(e);
  1403. }
  1404. }
  1405. }
  1406. impl Index<&ThreadHash> for Threads {
  1407. type Output = ThreadNode;
  1408. fn index(&self, index: &ThreadHash) -> &ThreadNode {
  1409. self.thread_nodes
  1410. .get(index)
  1411. .expect("thread index out of bounds")
  1412. }
  1413. }
  1414. fn node_build(
  1415. tree: &mut ThreadTree,
  1416. idx: ThreadHash,
  1417. sort: (SortField, SortOrder),
  1418. thread_nodes: &mut FnvHashMap<ThreadHash, ThreadNode>,
  1419. indentation: usize,
  1420. envelopes: &Envelopes,
  1421. ) {
  1422. if let Some(hash) = thread_nodes[&idx].message {
  1423. if !envelopes.contains_key(&hash) {
  1424. /* invalidate node */
  1425. // thread_nodes[&idx].message = None;
  1426. } else if let Some(parent_id) = thread_nodes[&idx].parent {
  1427. if let Some(parent_hash) = thread_nodes[&parent_id].message {
  1428. if !envelopes.contains_key(&parent_hash) {
  1429. /* invalidate node */
  1430. // thread_nodes[&parent_id].message = None;
  1431. } else {
  1432. /* decide if the subject should be shown in the UI.
  1433. * If parent subject is Foobar and reply is `Re: Foobar`
  1434. * then showing the reply's subject can be reduntant
  1435. */
  1436. let mut subject = envelopes[&hash].subject();
  1437. let mut subject = subject.to_mut().as_bytes();
  1438. subject.strip_prefixes();
  1439. let mut parent_subject = envelopes[&parent_hash].subject();
  1440. let mut parent_subject = parent_subject.to_mut().as_bytes();
  1441. parent_subject.strip_prefixes();
  1442. if subject == parent_subject {
  1443. thread_nodes.entry(idx).and_modify(|e| {
  1444. e.show_subject = false;
  1445. });
  1446. }
  1447. }
  1448. }
  1449. }
  1450. } else if let Some(node) = thread_nodes.get(&idx) {
  1451. if let (None, None, 0) = (node.parent, node.message, node.children.len()) {
  1452. return;
  1453. }
  1454. }
  1455. let indentation = if thread_nodes[&idx].has_message() {
  1456. thread_nodes
  1457. .entry(idx)
  1458. .and_modify(|e| e.indentation = indentation);
  1459. indentation + 1
  1460. } else if indentation > 0 {
  1461. indentation
  1462. } else {
  1463. indentation + 1
  1464. };
  1465. let mut has_unseen = if let Some(msg) = thread_nodes[&idx].message {
  1466. !envelopes[&msg].is_seen()
  1467. } else {
  1468. false
  1469. };
  1470. thread_nodes.entry(idx).and_modify(|e| {
  1471. e.len = e.children.len();
  1472. e.indentation = indentation
  1473. });
  1474. let mut child_vec: Vec<ThreadTree> = Vec::new();
  1475. /* No child/parent relationship is mutated at any point and no nodes are added or removed. Only
  1476. * each node's fields change, so the following is safe.
  1477. */
  1478. let children = &thread_nodes[&idx].children as *const Vec<ThreadHash>;
  1479. for &c in unsafe { &(*children) } {
  1480. let mut new_tree = ThreadTree::new(c);
  1481. node_build(
  1482. &mut new_tree,
  1483. c,
  1484. sort,
  1485. thread_nodes,
  1486. indentation + 1,
  1487. envelopes,
  1488. );
  1489. let _c = (thread_nodes[&c].len, thread_nodes[&c].date);
  1490. thread_nodes.entry(idx).and_modify(|e| {
  1491. e.len += _c.0;
  1492. e.date = cmp::max(e.date, _c.1);
  1493. });
  1494. has_unseen |= thread_nodes[&c].has_unseen;
  1495. ThreadTree::insert_child(&mut child_vec, new_tree, sort, thread_nodes, envelopes);
  1496. }
  1497. tree.children = child_vec;
  1498. thread_nodes.entry(idx).and_modify(|e| {
  1499. e.has_unseen = has_unseen;
  1500. });
  1501. }
  1502. fn print_threadnodes(
  1503. node_hash: ThreadHash,
  1504. nodes: &FnvHashMap<ThreadHash, ThreadNode>,
  1505. envelopes: &Envelopes,
  1506. ) {
  1507. fn help(
  1508. level: usize,
  1509. node_hash: ThreadHash,
  1510. nodes: &FnvHashMap<ThreadHash, ThreadNode>,
  1511. envelopes: &Envelopes,
  1512. ) {
  1513. eprint!("{}ThreadNode {}\n{}\tmessage: {}\n{}\tparent: {}\n{}\tthread_group: {}\n{}\tchildren (len: {}):\n",
  1514. "\t".repeat(level),
  1515. node_hash,
  1516. "\t".repeat(level),
  1517. nodes[&node_hash].message().as_ref().map(|m| format!("{} - {}\n{}\t\t{}", envelopes[m].message_id_display(), envelopes[m].subject(), "\t".repeat(level), envelopes[m].references().iter().map(ToString::to_string).collect::<Vec<String>>().join(", "))).unwrap_or_else(|| "None".to_string()),
  1518. "\t".repeat(level),
  1519. nodes[&node_hash].parent().as_ref().map(ToString::to_string).unwrap_or_else(|| "None".to_string()),
  1520. "\t".repeat(level),
  1521. nodes[&node_hash].thread_group,
  1522. "\t".repeat(level),
  1523. nodes[&node_hash].children.len(),
  1524. );
  1525. for c in &nodes[&node_hash].children {
  1526. help(level + 2, *c, nodes, envelopes);
  1527. }
  1528. }
  1529. help(0, node_hash, nodes, envelopes);
  1530. }