dust-mail 0.4.3

A multi protocol email client
Documentation
use async_imap::types::Name;

use crate::{
    client::incoming::types::mailbox::Mailbox,
    tree::{Find, Node},
};

pub struct MailboxFinder(String);

impl Find<Mailbox> for MailboxFinder {
    fn find(&self, item: &Mailbox) -> bool {
        item.id().to_lowercase() == self.0
    }
}

impl MailboxFinder {
    pub fn with_id<I: Into<String>>(id: I) -> Self {
        Self(Into::<String>::into(id).to_lowercase())
    }
}

pub fn build_mailbox_tree<L: IntoIterator<Item = Name>>(names: L) -> Node<Mailbox> {
    let names: Vec<Name> = names.into_iter().collect();

    let mut root: Node<Mailbox> = Node::empty_root();

    for name in &names {
        match name.delimiter() {
            Some(delimiter) => {
                let parts: Vec<_> = name.name().split(delimiter).collect();

                add_children(&names, &mut root, delimiter, parts, 0)
            }
            None => {
                root.insert(Node::empty_branch(name.into()));
            }
        }
    }

    Node::create_leaves(root)
}

fn add_children(
    names: &Vec<Name>,
    node: &mut Node<Mailbox>,
    delimiter: &str,
    parts: Vec<&str>,
    index: usize,
) {
    if let Some(_) = parts.get(index) {
        let id = parts[0..index + 1].join(delimiter);

        let child = node.find_mut(&MailboxFinder::with_id(&id));

        match child {
            Some(child) => add_children(names, child, delimiter, parts, index + 1),
            None => {
                if let Some(found) = names.iter().find(|child| child.name() == id) {
                    node.insert(Node::empty_branch(found.into()));

                    add_children(names, node, delimiter, parts, index);
                }
            }
        }
    }
}