rust-irc/src/client/data/response.rs
2015-06-22 12:03:57 -04:00

362 lines
14 KiB
Rust

//! Enumeration of all the possible server responses.
#![allow(non_camel_case_types)]
use std::mem::transmute;
use std::str::FromStr;
use client::data::message::Message;
/// List of all server responses as defined in [RFC 2812](http://tools.ietf.org/html/rfc2812).
/// All commands are documented with their expected form from the RFC.
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u16)]
pub enum Response {
// Expected replies
/// 001 Welcome to the Internet Relay Network <nick>!<user>@<host>
RPL_WELCOME = 001,
/// 002 Your host is <servername>, running version <ver>
RPL_YOURHOST = 002,
/// 003 This server was created <date>
RPL_CREATED = 003,
/// 004 <servername> <version> <available user modes> available channel modes>
RPL_MYINFO = 004,
/// 005 Try server <server name>, port <port number>
RPL_BOUNCE = 005,
/// 302 :*1<reply> *( " " <reply> )
RPL_USERHOST = 302,
/// 303 :*1<nick> *( " " <nick> )
RPL_ISON = 303,
/// 301 <nick> :<away message>
RPL_AWAY = 301,
/// 305 :You are no longer marked as being away
RPL_UNAWAY = 305,
/// 306 :You have been marked as being away
RPL_NOWAWAY = 306,
/// 311 <nick> <user> <host> * :<real name>
RPL_WHOISUSER = 311,
/// 312 <nick> <server> :<server info>
RPL_WHOISSERVER = 312,
/// 313 <nick> :is an IRC operator
RPL_WHOISOPERATOR = 313,
/// 317 <nick> <integer> :seconds idle
RPL_WHOISIDLE = 317,
/// 318 <nick> :End of WHOIS list
RPL_ENDOFWHOIS = 318,
/// 319 <nick> :*( ( "@" / "+" ) <channel> " " )
RPL_WHOISCHANNELS = 319,
/// 314 <nick> <user> <host> * :<real name>
RPL_WHOWASUSER = 314,
/// 369 <nick> :End of WHOWAS
RPL_ENDOFWHOWAS = 369,
/// Obsolete. Not used.
RPL_LISTSTART = 321,
/// 322 <channel> <# visible> :<topic>
RPL_LIST = 322,
/// 323 :End of LIST
RPL_LISTEND = 323,
/// 325 <channel> <nickname>
RPL_UNIQOPIS = 325,
/// 324 <channel> <mode> <mode params>
RPL_CHANNELMODEIS = 324,
/// 331 <channel> :No topic is set
RPL_NOTOPIC = 331,
/// 332 <channel> :<topic>
RPL_TOPIC = 332,
/// 341 <channel> <nick>
RPL_INVITING = 341,
/// 342 <user> :Summoning user to IRC
RPL_SUMMONING = 342,
/// 346 <channel> <invitemask>
RPL_INVITELIST = 346,
/// 347 <channel> :End of channel invite list
RPL_ENDOFINVITELIST = 347,
/// 348 <channel> <exceptionmask>
RPL_EXCEPTLIST = 348,
/// 349 <channel> :End of channel exception list
RPL_ENDOFEXCEPTLIST = 349,
/// 351 <version>.<debuglevel> <server> :<comments>
RPL_VERSION = 351,
/// 352 <channel> <user> <host> <server> <nick> ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
/// :<hopcount> <real name>
RPL_WHOREPLY = 352,
/// 315 <name> :End of WHO list
RPL_ENDOFWHO = 315,
/// 353 ( "=" / "*" / "@" ) <channel> :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
RPL_NAMREPLY = 353,
/// 366 <channel> :End of NAMES list
RPL_ENDOFNAMES = 366,
/// 364 <mask> <server> :<hopcount> <server info>
RPL_LINKS = 364,
/// 365 <mask> :End of LINKS list
RPL_ENDOFLINKS = 365,
/// 367 <channel> <banmask>
RPL_BANLIST = 367,
/// 368 <channel> :End of channel ban list
RPL_ENDOFBANLIST = 368,
/// 371 :<string>
RPL_INFO = 371,
/// 374 :End of INFO list
RPL_ENDOFINFO = 374,
/// 375 :- <server> Message of the day -
RPL_MOTDSTART = 375,
/// 372 :- <text>
RPL_MOTD = 372,
/// 376 :End of MOTD command
RPL_ENDOFMOTD = 376,
/// 381 :You are now an IRC operator
RPL_YOUREOPER = 381,
/// 382 <config file> :Rehashing
RPL_REHASHING = 382,
/// 383 You are service <servicename>
RPL_YOURESERVICE = 383,
/// 391 <server> :<string showing server's local time>
RPL_TIME = 391,
/// 392 :UserID Terminal Host
RPL_USERSSTART = 392,
/// 393 :<username> <ttyline> <hostname>
RPL_USERS = 393,
/// 394 :End of users
RPL_ENDOFUSERS = 394,
/// 395 :Nobody logged in
RPL_NOUSERS = 395,
/// 200 Link <version & debug level> <destination> <next server> V<protocol version>
/// <link uptime in seconds> <backstream sendq> <upstream sendq>
RPL_TRACELINK = 200,
/// 201 Try. <class> <server>
RPL_TRACECONNECTING = 201,
/// 202 H.S. <class> <server>
RPL_TRACEHANDSHAKE = 202,
/// 203 ???? <class> [<client IP address in dot form>]
RPL_TRACEUKNOWN = 203,
/// 204 Oper <class> <nick>
RPL_TRACEOPERATOR = 204,
/// 205 User <class> <nick>
RPL_TRACEUSER = 205,
/// 206 Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> V<protocol version>
RPL_TRACESERVER = 206,
/// 207 Service <class> <name> <type> <active type>
RPL_TRACESERVICE = 207,
/// 208 <newtype> 0 <client name>
RPL_TRACENEWTYPE = 208,
/// 209 Class <class> <count>
RPL_TRACECLASS = 209,
/// Unused.
RPL_TRACERECONNECT = 210,
/// 261 File <logfile> <debug level>
RPL_TRACELOG = 261,
/// 262 <server name> <version & debug level> :End of TRACE
RPL_TRACEEND = 262,
/// 211 <linkname> <sendq> <sent messages> <sent Kbytes> <received messages> <received Kbytes>
/// <time open>
RPL_STATSLINKINFO = 211,
/// 212 <command> <count> <byte count> <remote count>
RPL_STATSCOMMANDS = 212,
/// 219 <stats letter> :End of STATS report
RPL_ENDOFSTATS = 219,
/// 242 :Server Up %d days %d:%02d:%02d
RPL_STATSUPTIME = 242,
/// O <hostmask> * <name>
RPL_STATSOLINE = 243,
/// 221 <user mode string>
RPL_UMODEIS = 221,
/// 234 <name> <server> <mask> <type> <hopcount> <info>
RPL_SERVLIST = 234,
/// 235 <mask> <type> :End of service listing
RPL_SERVLISTEND = 235,
/// 251 :There are <integer> users and <integer> services on <integer> servers
RPL_LUSERCLIENT = 251,
/// 252 <integer> :operator(s) online
RPL_LUSEROP = 252,
/// 253 <integer> :unknown connection(s)
RPL_LUSERUNKNOWN = 253,
/// 254 <integer> :channels formed
RPL_LUSERCHANNELS = 254,
/// 255 :I have <integer> clients and <integer> servers
RPL_LUSERME = 255,
/// 256 <server> :Administrative info
RPL_ADMINME = 256,
/// 257 :<admin info>
RPL_ADMINLOC1 = 257,
/// 258 :<admin info>
RPL_ADMINLOC2 = 258,
/// 259 :<admin info>
RPL_ADMINEMAIL = 259,
/// 263 <command> :Please wait a while and try again.
RPL_TRYAGAIN = 263,
/// 730 <nick> :target[,target2]*
RPL_MONONLINE = 730,
/// 731 <nick> :target[,target2]*
RPL_MONOFFLINE = 731,
/// 732 <nick> :target[,target2]*
RPL_MONLIST = 732,
/// 733 <nick> :End of MONITOR list
RPL_ENDOFMONLIST = 733,
// Error replies
/// 401 <nickname> :No such nick/channel
ERR_NOSUCHNICK = 401,
/// 402 <server name> :No such server
ERR_NOSUCHSERVER = 402,
/// 403 <channel name> :No such channel
ERR_NOSUCHCHANNEL = 403,
/// 404 <channel name> :Cannot send to channel
ERR_CANNOTSENDTOCHAN = 404,
/// 405 <channel name> :You have joined too many channels
ERR_TOOMANYCHANNELS = 405,
/// 406 <nickname> :There was no such nickname
ERR_WASNOSUCHNICK = 406,
/// 407 <target> :<error code> recipients. <abort message>
ERR_TOOMANYTARGETS = 407,
/// 408 <service name> :No such service
ERR_NOSUCHSERVICE = 408,
/// 409 :No origin specified
ERR_NOORIGIN = 409,
/// 411 :No recipient given (<command>)
ERR_NORECIPIENT = 411,
/// 412 :No text to send
ERR_NOTEXTTOSEND = 412,
/// 413 <mask> :No toplevel domain specified
ERR_NOTOPLEVEL = 413,
/// 414 <mask> :Wildcard in toplevel domain
ERR_WILDTOPLEVEL = 414,
/// 415 <mask> :Bad Server/host mask
ERR_BADMASK = 415,
/// 421 <command> :Unknown command
ERR_UNKNOWNCOMMAND = 421,
/// 422 :MOTD File is missing
ERR_NOMOTD = 422,
/// 423 <server> :No administrative info available
ERR_NOADMININFO = 423,
/// 424 :File error doing <file op> on <file>
ERR_FILEERROR = 424,
/// 431 :No nickname given
ERR_NONICKNAMEGIVEN = 431,
/// 432 <nick> :Erroneous nickname"
ERR_ERRONEOUSNICKNAME = 432,
/// 433 <nick> :Nickname is already in use
ERR_NICKNAMEINUSE = 433,
/// 436 <nick> :Nickname collision KILL from <user>@<host>
ERR_NICKCOLLISION = 436,
/// 437 <nick/channel> :Nick/channel is temporarily unavailable
ERR_UNAVAILRESOURCE = 437,
/// 441 <nick> <channel> :They aren't on that channel
ERR_USERNOTINCHANNEL = 441,
/// 442 <channel> :You're not on that channel
ERR_NOTONCHANNEL = 442,
/// 443 <user> <channel> :is already on channel
ERR_USERONCHANNEL = 443,
/// 444 <user> :User not logged in
ERR_NOLOGIN = 444,
/// 445 :SUMMON has been disabled
ERR_SUMMONDISABLED = 445,
/// 446 :USERS has been disabled
ERR_USERSDISABLED = 446,
/// 451 :You have not registered
ERR_NOTREGISTERED = 451,
/// 461 <command> :Not enough parameters
ERR_NEEDMOREPARAMS = 461,
/// 462 :Unauthorized command (already registered)
ERR_ALREADYREGISTRED = 462,
/// 463 :Your host isn't among the privileged
ERR_NOPERMFORHOST = 463,
/// 464 :Password incorrect
ERR_PASSWDMISMATCH = 464,
/// 465 :You are banned from this server
ERR_YOUREBANNEDCREEP = 465,
/// 466
ERR_YOUWILLBEBANNED = 466,
/// 467 <channel> :Channel key already set
ERR_KEYSET = 467,
/// 471 <channel> :Cannot join channel (+l)
ERR_CHANNELISFULL = 471,
/// 472 <char> :is unknown mode char to me for <channel>
ERR_UNKNOWNMODE = 472,
/// 473 <channel> :Cannot join channel (+i)
ERR_INVITEONLYCHAN = 473,
/// 474 <channel> :Cannot join channel (+b)
ERR_BANNEDFROMCHAN = 474,
/// 475 <channel> :Cannot join channel (+k)
ERR_BADCHANNELKEY = 475,
/// 476 <channel> :Bad Channel Mask
ERR_BADCHANMASK = 476,
/// 477 <channel> :Channel doesn't support modes
ERR_NOCHANMODES = 477,
/// 478 <channel> <char> :Channel list is full
ERR_BANLISTFULL = 478,
/// 481 :Permission Denied- You're not an IRC operator
ERR_NOPRIVILEGES = 481,
/// 482 <channel> :You're not channel operator
ERR_CHANOPRIVSNEEDED = 482,
/// 483 :You can't kill a server!
ERR_CANTKILLSERVER = 483,
/// 484 :Your connection is restricted!
ERR_RESTRICTED = 484,
/// 485 :You're not the original channel operator
ERR_UNIQOPPRIVSNEEDED = 485,
/// 491 :No O-lines for your host
ERR_NOOPERHOST = 491,
/// 501 :Unknown MODE flag
ERR_UMODEUNKNOWNFLAG = 501,
/// 502 :Cannot change mode for other users
ERR_USERSDONTMATCH = 502,
/// 734 <nick> <limit> <targets> :Monitor list is full.
ERR_MONLISTFULL = 734,
}
impl Response {
/// Gets a response from a message.
pub fn from_message(m: &Message) -> Option<Response> {
m.command.parse().ok()
}
/// Determines whether or not this response is an error response.
pub fn is_error(&self) -> bool {
*self as u16 >= 400
}
}
impl FromStr for Response {
type Err = &'static str;
fn from_str(s: &str) -> Result<Response, &'static str> {
if let Ok(rc) = s.parse::<u16>() {
// This wall of text was brought to you by the removal of FromPrimitive.
if (rc > 0 && rc < 5) || (rc > 200 && rc < 213) || rc == 219 || rc == 221 || rc == 234
|| rc == 235 || rc == 242 || rc == 243 || (rc > 250 && rc < 260) ||
(rc > 260 && rc < 264) || (rc > 300 && rc < 307) ||
(rc > 310 && rc < 326 && rc != 320) || rc == 331 || rc == 332 || rc == 341 ||
rc == 342 || (rc > 345 && rc < 354 && rc != 350) ||
(rc > 363 && rc < 377 && rc != 370) || (rc > 380 && rc < 384) ||
(rc > 390 && rc < 396) || (rc > 400 && rc < 415 && rc != 410) ||
(rc > 420 && rc < 425) || (rc > 430 && rc < 434) || rc == 436 || rc == 437 ||
(rc > 440 && rc < 447) || rc == 451 || (rc > 460 && rc < 468) ||
(rc > 470 && rc < 479) || (rc > 480 && rc < 486) || rc == 491 || rc == 501 ||
rc == 502 || (rc > 729 && rc < 735) {
Ok(unsafe { transmute(rc) })
} else {
Err("Failed to parse due to unknown response code.")
}
} else {
Err("Failed to parse response code.")
}
}
}
#[cfg(test)]
mod test {
use super::Response;
#[test]
fn from_message() {
assert_eq!(Response::from_message(
&":irc.test.net 353 test = #test :test\r\n".into()
).unwrap(), Response::RPL_NAMREPLY);
assert_eq!(Response::from_message(
&":irc.test.net 433 <nick> :Nickname is already in use\r\n".into()
).unwrap(), Response::ERR_NICKNAMEINUSE);
}
#[test]
fn is_error() {
assert!(!Response::RPL_NAMREPLY.is_error());
assert!(Response::ERR_NICKNAMEINUSE.is_error());
}
}