1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use std::collections::HashMap; use std::sync::Arc; use super::super::*; #[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<&'static str, (&'static Command, Arc<CommandMap>)>, min_length: usize, max_length: usize, } impl CommandMap { pub fn new(cmds: &[&'static Command]) -> Self { let mut map = Self::default(); for cmd in cmds { let sub_map = Arc::new(Self::new(&cmd.options.sub_commands)); 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); map.cmds.insert(*name, (*cmd, sub_map.clone())); } } 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]) -> Self { let mut map = Self::default(); for group in groups { let subgroups_map = Arc::new(Self::new(&group.options.sub_groups)); let commands_map = Arc::new(CommandMap::new(&group.options.commands)); 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, subgroups_map.clone(), commands_map.clone())); } } 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() } }