serenity 0.12.5

A Rust library for the Discord API.
Documentation
use crate::framework::standard::*;

#[derive(Debug)]
pub enum Map {
    WithPrefixes(GroupMap),
    Prefixless(GroupMap, CommandMap),
}

pub trait ParseMap {
    type Storage;

    fn get(&self, n: &str) -> Option<Self::Storage>;
    fn min_length(&self) -> usize;
    fn max_length(&self) -> usize;
    fn is_empty(&self) -> bool;
}

#[derive(Debug, Default)]
pub struct CommandMap {
    cmds: HashMap<String, (&'static Command, Arc<CommandMap>)>,
    min_length: usize,
    max_length: usize,
}

impl CommandMap {
    pub fn new(cmds: &[&'static Command], conf: &Configuration) -> Self {
        let mut map = Self::default();

        for cmd in cmds {
            let sub_map = Arc::new(Self::new(cmd.options.sub_commands, conf));

            for name in cmd.options.names {
                let len = name.chars().count();
                map.min_length = std::cmp::min(len, map.min_length);
                map.max_length = std::cmp::max(len, map.max_length);

                let name =
                    if conf.case_insensitive { name.to_lowercase() } else { (*name).to_string() };

                map.cmds.insert(name, (*cmd, Arc::clone(&sub_map)));
            }
        }

        map
    }
}

impl ParseMap for CommandMap {
    type Storage = (&'static Command, Arc<CommandMap>);

    #[inline]
    fn min_length(&self) -> usize {
        self.min_length
    }

    #[inline]
    fn max_length(&self) -> usize {
        self.max_length
    }

    #[inline]
    fn get(&self, name: &str) -> Option<Self::Storage> {
        self.cmds.get(name).cloned()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.cmds.is_empty()
    }
}

#[derive(Debug, Default)]
pub struct GroupMap {
    groups: HashMap<&'static str, (&'static CommandGroup, Arc<GroupMap>, Arc<CommandMap>)>,
    min_length: usize,
    max_length: usize,
}

impl GroupMap {
    pub fn new(groups: &[&'static CommandGroup], conf: &Configuration) -> Self {
        let mut map = Self::default();

        for group in groups {
            let subgroups_map = Arc::new(Self::new(group.options.sub_groups, conf));
            let commands_map = Arc::new(CommandMap::new(group.options.commands, conf));

            for prefix in group.options.prefixes {
                let len = prefix.chars().count();
                map.min_length = std::cmp::min(len, map.min_length);
                map.max_length = std::cmp::max(len, map.max_length);

                map.groups.insert(
                    *prefix,
                    (*group, Arc::clone(&subgroups_map), Arc::clone(&commands_map)),
                );
            }
        }

        map
    }
}

impl ParseMap for GroupMap {
    type Storage = (&'static CommandGroup, Arc<GroupMap>, Arc<CommandMap>);

    #[inline]
    fn min_length(&self) -> usize {
        self.min_length
    }

    #[inline]
    fn max_length(&self) -> usize {
        self.max_length
    }

    #[inline]
    fn get(&self, name: &str) -> Option<Self::Storage> {
        self.groups.get(&name).cloned()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.groups.is_empty()
    }
}