ellidri-tokens 0.1.0

Parse IRC like a boss
Documentation
use std::fmt;

macro_rules! commands {
    ( $( $cmd:ident $cmd_str:literal $n:literal )* ) => {
        /// The list of known commands.
        ///
        /// Unknown commands and replies are supported by `Message` directly, this enum just
        /// contains the supported commands.
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum Command {
            $( $cmd, )*
            Reply(&'static str),
        }

        impl Command {
            /// From a given command string, returns the corresponding command, or `None`
            /// otherwise.
            ///
            /// It ignores the case of its argument.
            ///
            /// # Example
            ///
            /// ```rust
            /// # use ellidri_tokens::Command;
            /// let join = Command::parse("join");
            /// let join2 = Command::parse("JOIN");
            /// let not_join = Command::parse("not_join");
            ///
            /// assert_eq!(join, Some(Command::Join));
            /// assert_eq!(join2, Some(Command::Join));
            /// assert_eq!(not_join, None);
            /// ```
            pub fn parse(s: &str) -> Option<Self> {
                $( if s.eq_ignore_ascii_case($cmd_str) {
                    Some(Command::$cmd)
                } else )* {
                    None
                }
            }

            /// Returns the number of required arguments for the command.
            ///
            /// The command may accept more arguments.
            ///
            /// # Example
            ///
            /// ```rust
            /// # use ellidri_tokens::Command;
            /// let privmsg = Command::parse("Privmsg").unwrap();
            /// let topic = Command::parse("TOPIC").unwrap();
            ///
            /// assert_eq!(privmsg.required_params(), 2);
            /// assert_eq!(topic.required_params(), 1);
            /// ```
            pub fn required_params(&self) -> usize {
                match self {
                $(
                    Command::$cmd => $n,
                )*
                    Command::Reply(_) => 0,
                }
            }

            /// Returns the command string. It is not the string that have been parsed.
            ///
            /// # Example
            ///
            /// ```rust
            /// # use ellidri_tokens::Command;
            /// let quit = Command::parse("Quit").unwrap();
            ///
            /// assert_eq!(quit.as_str(), "QUIT");
            /// ```
            pub fn as_str(&self) -> &'static str {
                match self {
                $(
                    Command::$cmd => $cmd_str,
                )*
                    Command::Reply(s) => s,
                }
            }
        }

        impl From<&'static str> for Command {
            /// `&'static str`s are converted to the `Command::Reply` variant.
            ///
            /// This trait is used by `Buffer` to accept both `Command` and `Reply` when
            /// building messages.
            fn from(reply: &'static str) -> Self {
                Command::Reply(reply)
            }
        }

        impl fmt::Display for Command {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                self.as_str().fmt(f)
            }
        }
    }
}

commands! {
//  Ident.   String     Minimum # of params
    Admin    "ADMIN"    0
    Authenticate "AUTHENTICATE" 1
    Away     "AWAY"     0
    Cap      "CAP"      1
    Info     "INFO"     0
    Invite   "INVITE"   2
    Join     "JOIN"     1
    Kick     "KICK"     2
    Kill     "KILL"     2
    List     "LIST"     0
    Lusers   "LUSERS"   0
    Mode     "MODE"     1
    Motd     "MOTD"     0
    Names    "NAMES"    0
    Nick     "NICK"     1
    Notice   "NOTICE"   2
    Oper     "OPER"     2
    Part     "PART"     1
    Pass     "PASS"     1
    Ping     "PING"     1
    Pong     "PONG"     1
    PrivMsg  "PRIVMSG"  2
    Quit     "QUIT"     0
    Rehash   "REHASH"   0
    SetName  "SETNAME"  1
    TagMsg   "TAGMSG"   1
    Time     "TIME"     0
    Topic    "TOPIC"    1
    User     "USER"     4
    Version  "VERSION"  0
    Who      "WHO"      0
    Whois    "WHOIS"    1
}