Skip to main content

ellidri_tokens/
command.rs

1use std::fmt;
2
3macro_rules! commands {
4    ( $( $cmd:ident $cmd_str:literal $n:literal )* ) => {
5        /// The list of known commands.
6        ///
7        /// Unknown commands and replies are supported by `Message` directly, this enum just
8        /// contains the supported commands.
9        #[derive(Clone, Copy, Debug, PartialEq)]
10        pub enum Command {
11            $( $cmd, )*
12            Reply(&'static str),
13        }
14
15        impl Command {
16            /// From a given command string, returns the corresponding command, or `None`
17            /// otherwise.
18            ///
19            /// It ignores the case of its argument.
20            ///
21            /// # Example
22            ///
23            /// ```rust
24            /// # use ellidri_tokens::Command;
25            /// let join = Command::parse("join");
26            /// let join2 = Command::parse("JOIN");
27            /// let not_join = Command::parse("not_join");
28            ///
29            /// assert_eq!(join, Some(Command::Join));
30            /// assert_eq!(join2, Some(Command::Join));
31            /// assert_eq!(not_join, None);
32            /// ```
33            pub fn parse(s: &str) -> Option<Self> {
34                $( if s.eq_ignore_ascii_case($cmd_str) {
35                    Some(Command::$cmd)
36                } else )* {
37                    None
38                }
39            }
40
41            /// Returns the number of required arguments for the command.
42            ///
43            /// The command may accept more arguments.
44            ///
45            /// # Example
46            ///
47            /// ```rust
48            /// # use ellidri_tokens::Command;
49            /// let privmsg = Command::parse("Privmsg").unwrap();
50            /// let topic = Command::parse("TOPIC").unwrap();
51            ///
52            /// assert_eq!(privmsg.required_params(), 2);
53            /// assert_eq!(topic.required_params(), 1);
54            /// ```
55            pub fn required_params(&self) -> usize {
56                match self {
57                $(
58                    Command::$cmd => $n,
59                )*
60                    Command::Reply(_) => 0,
61                }
62            }
63
64            /// Returns the command string. It is not the string that have been parsed.
65            ///
66            /// # Example
67            ///
68            /// ```rust
69            /// # use ellidri_tokens::Command;
70            /// let quit = Command::parse("Quit").unwrap();
71            ///
72            /// assert_eq!(quit.as_str(), "QUIT");
73            /// ```
74            pub fn as_str(&self) -> &'static str {
75                match self {
76                $(
77                    Command::$cmd => $cmd_str,
78                )*
79                    Command::Reply(s) => s,
80                }
81            }
82        }
83
84        impl From<&'static str> for Command {
85            /// `&'static str`s are converted to the `Command::Reply` variant.
86            ///
87            /// This trait is used by `Buffer` to accept both `Command` and `Reply` when
88            /// building messages.
89            fn from(reply: &'static str) -> Self {
90                Command::Reply(reply)
91            }
92        }
93
94        impl fmt::Display for Command {
95            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96                self.as_str().fmt(f)
97            }
98        }
99    }
100}
101
102commands! {
103//  Ident.   String     Minimum # of params
104    Admin    "ADMIN"    0
105    Authenticate "AUTHENTICATE" 1
106    Away     "AWAY"     0
107    Cap      "CAP"      1
108    Info     "INFO"     0
109    Invite   "INVITE"   2
110    Join     "JOIN"     1
111    Kick     "KICK"     2
112    Kill     "KILL"     2
113    List     "LIST"     0
114    Lusers   "LUSERS"   0
115    Mode     "MODE"     1
116    Motd     "MOTD"     0
117    Names    "NAMES"    0
118    Nick     "NICK"     1
119    Notice   "NOTICE"   2
120    Oper     "OPER"     2
121    Part     "PART"     1
122    Pass     "PASS"     1
123    Ping     "PING"     1
124    Pong     "PONG"     1
125    PrivMsg  "PRIVMSG"  2
126    Quit     "QUIT"     0
127    Rehash   "REHASH"   0
128    SetName  "SETNAME"  1
129    TagMsg   "TAGMSG"   1
130    Time     "TIME"     0
131    Topic    "TOPIC"    1
132    User     "USER"     4
133    Version  "VERSION"  0
134    Who      "WHO"      0
135    Whois    "WHOIS"    1
136}