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}