use std::str::FromStr; use std::borrow::{ Cow, ToOwned }; use std::borrow::Cow::*; use ::{ Result, IrscError }; use ::message::Message; macro_rules! replies { ($( $name: ident { $id: expr, $doc: meta b $($borrowed_items: ty),* o $($owned_items: ty),* t $($to_names: ident),+ => $($to_exprs: expr),+ }),+) => ( #[allow(non_camel_case_types)] #[derive(Debug, Hash, Clone, PartialEq, Eq)] pub enum Reply<'a> { $( #[$doc] $name($($borrowed_items),*) ),+ } #[allow(non_camel_case_types)] #[derive(Debug, Hash, Clone, PartialEq, Eq)] pub enum OwnedReply { $( #[$doc] $name($($owned_items),*) ),+ } impl<'a> Reply<'a> { pub fn to_owned(self) -> OwnedReply { match self { $( Reply::$name($($to_names),*) => OwnedReply::$name($($to_exprs),*) ),+ } } pub fn from_message(msg: &'a Message) -> Option> { use Reply::*; match msg.command() { $( $id => msg.last().map(|&e| $name(e)) ),+ } } pub fn to_message(&self) -> Message { use Reply::*; match self { $( &$name(ref s) => Message::format(None, $id, Vec::new(), s) ),+ } } } ) } replies! { RPL_WELCOME { "001", doc = r#"001 RPL_WELCOME "Welcome to the Internet Relay Network !@""# b &'a [u8] o Vec t s => s.into() }, RPL_YOURHOST { "002", doc = r#"002 RPL_YOURHOST "Your host is , running version ""# b &'a [u8] o Vec t s => s.into() }, RPL_CREATED { "003", doc = r#"003 RPL_CREATED "This server was created ""# b &'a [u8] o Vec t s => s.into() }, RPL_MYINFO { "004", doc = r#"004 RPL_MYINFO " " - The server sends Replies 001 to 004 to a user upon successful registration."# b &'a [u8], &'a [u8], &'a [u8] o Vec t s => s.into() } } /* RPL_MYINFO(&'a [u8]), /// 005 RPL_BOUNCE /// "Try server , port " /// /// - Sent by the server to a user to suggest an alternative /// server. This is often used when the connection is /// refused because the server is already full. /// RPL_BOUNCE(&'a [u8]), /// 302 RPL_USERHOST /// ":*1 *( " " )" /// /// - Reply format used by USERHOST to list replies to /// the query list. The reply string is composed as /// follows: /// /// reply = nickname [ "*" ] "=" ( "+" / "-" ) hostname /// /// The '*' indicates whether the client has registered /// as an Operator. The '-' or '+' characters represent /// whether the client has set an AWAY message or not /// respectively. /// RPL_USERHOST(&'a [u8]), /// 303 RPL_ISON /// ":*1 *( " " )" /// /// - Reply format used by ISON to list replies to the /// query list. /// RPL_ISON(&'a [u8]), /// 301 RPL_AWAY /// " :" RPL_AWAY(&'a [u8]), /// 305 RPL_UNAWAY /// ":You are no longer marked as being away" RPL_UNAWAY(&'a [u8]), /// 306 RPL_NOWAWAY /// ":You have been marked as being away" /// /// - These replies are used with the AWAY command (if /// allowed). RPL_AWAY is sent to any client sending a /// PRIVMSG to a client which is away. RPL_AWAY is only /// sent by the server to which the client is connected. /// Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the /// client removes and sets an AWAY message. /// RPL_NOWAWAY(&'a [u8]), /// 311 RPL_WHOISUSER /// " * :" RPL_WHOISUSER(&'a [u8]), /// 312 RPL_WHOISSERVER /// " :" RPL_WHOISSERVER(&'a [u8]), /// 313 RPL_WHOISOPERATOR /// " :is an IRC operator" RPL_WHOISOPERATOR(&'a [u8]), /// 317 RPL_WHOISIDLE /// " :seconds idle" RPL_WHOISIDLE(&'a [u8]), /// 318 RPL_ENDOFWHOIS /// " :End of WHOIS list" RPL_ENDOFWHOIS(&'a [u8]), /// 319 RPL_WHOISCHANNELS /// " :*( ( "@" / "+" ) " " )" /// /// - Replies 311 - 313, 317 - 319 are all replies /// generated in response to a WHOIS message. Given that /// there are enough parameters present, the answering /// server MUST either formulate a reply out of the above /// numerics (if the query nick is found) or return an /// error reply. The '*' in RPL_WHOISUSER is there as /// the literal character and not as a wild card. For /// each reply set, only RPL_WHOISCHANNELS may appear /// more than once (for long lists of channel names). /// The '@' and '+' characters next to the channel name /// indicate whether a client is a channel operator or /// has been granted permission to speak on a moderated /// channel. The RPL_ENDOFWHOIS reply is used to mark /// the end of processing a WHOIS message. /// RPL_WHOISCHANNELS(&'a [u8]), /// 314 RPL_WHOWASUSER /// " * :" RPL_WHOWASUSER(&'a [u8]), /// 369 RPL_ENDOFWHOWAS /// " :End of WHOWAS" /// /// - When replying to a WHOWAS message, a server MUST use /// the replies RPL_WHOWASUSER, RPL_WHOISSERVER or /// ERR_WASNOSUCHNICK for each nickname in the presented /// list. At the end of all reply batches, there MUST /// be RPL_ENDOFWHOWAS (even if there was only one reply /// and it was an error). /// RPL_ENDOFWHOWAS(&'a [u8]), /// 321 RPL_LISTSTART /// Obsolete. Not used. /// RPL_LISTSTART, /// 322 RPL_LIST /// " <# visible> :" RPL_LIST(&'a [u8]), /// 323 RPL_LISTEND /// ":End of LIST" /// /// - Replies RPL_LIST, RPL_LISTEND mark the actual replies /// with data and end of the server's response to a LIST /// command. If there are no channels available to return, /// only the end reply MUST be sent. /// RPL_LISTEND(&'a [u8]), /// 325 RPL_UNIQOPIS /// " " /// RPL_UNIQOPIS(&'a [u8]), /// 324 RPL_CHANNELMODEIS /// " " /// RPL_CHANNELMODEIS(&'a [u8]), /// 331 RPL_NOTOPIC /// " :No topic is set" RPL_NOTOPIC(&'a [u8]), /// 332 RPL_TOPIC /// " :" /// /// - When sending a TOPIC message to determine the /// channel topic, one of two replies is sent. If /// the topic is set, RPL_TOPIC is sent back else /// RPL_NOTOPIC. /// RPL_TOPIC(&'a [u8]), /// 341 RPL_INVITING /// " " /// /// - Returned by the server to indicate that the /// attempted INVITE message was successful and is /// being passed onto the end client. /// RPL_INVITING(&'a [u8]), /// 342 RPL_SUMMONING /// " :Summoning user to IRC" /// /// - Returned by a server answering a SUMMON message to /// indicate that it is summoning that user. /// RPL_SUMMONING(&'a [u8]), /// 346 RPL_INVITELIST /// " " RPL_INVITELIST(&'a [u8]), /// 347 RPL_ENDOFINVITELIST /// " :End of channel invite list" /// /// - When listing the 'invitations masks' for a given channel, /// a server is required to send the list back using the /// RPL_INVITELIST and RPL_ENDOFINVITELIST messages. A /// separate RPL_INVITELIST is sent for each active mask. /// After the masks have been listed (or if none present) a /// RPL_ENDOFINVITELIST MUST be sent. /// RPL_ENDOFINVITELIST(&'a [u8]), /// 348 RPL_EXCEPTLIST /// " " RPL_EXCEPTLIST(&'a [u8]), /// 349 RPL_ENDOFEXCEPTLIST /// " :End of channel exception list" /// /// - When listing the 'exception masks' for a given channel, /// a server is required to send the list back using the /// RPL_EXCEPTLIST and RPL_ENDOFEXCEPTLIST messages. A /// separate RPL_EXCEPTLIST is sent for each active mask. /// After the masks have been listed (or if none present) /// a RPL_ENDOFEXCEPTLIST MUST be sent. /// RPL_ENDOFEXCEPTLIST(&'a [u8]), /// 351 RPL_VERSION /// ". :" /// /// - Reply by the server showing its version details. /// The is the version of the software being /// used (including any patchlevel revisions) and the /// is used to indicate if the server is /// running in "debug mode". /// /// The "comments" field may contain any comments about /// the version or further version details. /// RPL_VERSION(&'a [u8]), /// 352 RPL_WHOREPLY /// " /// ( "H" / "G" > ["*"] [ ( "@" / "+" ) ] /// : " /// RPL_WHOREPLY(&'a [u8]), /// 315 RPL_ENDOFWHO /// " :End of WHO list" /// /// - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used /// to answer a WHO message. The RPL_WHOREPLY is only /// sent if there is an appropriate match to the WHO /// query. If there is a list of parameters supplied /// with a WHO message, a RPL_ENDOFWHO MUST be sent /// after processing each list item with being /// the item. /// RPL_ENDOFWHO(&'a [u8]), /// 353 RPL_NAMREPLY /// "( "=" / "*" / "@" ) /// :[ "@" / "+" ] *( " " [ "@" / "+" ] ) /// - "@" is used for secret channels, "*" for private /// channels, and "=" for others (public channels). /// RPL_NAMREPLY(&'a [u8]), /// 366 RPL_ENDOFNAMES /// " :End of NAMES list" /// /// - To reply to a NAMES message, a reply pair consisting /// of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the /// server back to the client. If there is no channel /// found as in the query, then only RPL_ENDOFNAMES is /// returned. The exception to this is when a NAMES /// message is sent with no parameters and all visible /// channels and contents are sent back in a series of /// RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark /// the end. /// RPL_ENDOFNAMES(&'a [u8]), /// 364 RPL_LINKS /// " : " RPL_LINKS(&'a [u8]), /// 365 RPL_ENDOFLINKS /// " :End of LINKS list" /// /// - In replying to the LINKS message, a server MUST send /// replies back using the RPL_LINKS numeric and mark the /// end of the list using an RPL_ENDOFLINKS reply. /// RPL_ENDOFLINKS(&'a [u8]), /// 367 RPL_BANLIST /// " " RPL_BANLIST(&'a [u8]), /// 368 RPL_ENDOFBANLIST /// " :End of channel ban list" /// /// - When listing the active 'bans' for a given channel, /// a server is required to send the list back using the /// RPL_BANLIST and RPL_ENDOFBANLIST messages. A separate /// RPL_BANLIST is sent for each active banmask. After the /// banmasks have been listed (or if none present) a /// RPL_ENDOFBANLIST MUST be sent. /// RPL_ENDOFBANLIST(&'a [u8]), /// 371 RPL_INFO /// ":" RPL_INFO(&'a [u8]), /// 374 RPL_ENDOFINFO /// ":End of INFO list" /// /// - A server responding to an INFO message is required to /// send all its 'info' in a series of RPL_INFO messages /// with a RPL_ENDOFINFO reply to indicate the end of the /// replies. /// RPL_ENDOFINFO(&'a [u8]), /// 375 RPL_MOTDSTART /// ":- Message of the day - " RPL_MOTDSTART(&'a [u8]), /// 372 RPL_MOTD /// ":- " RPL_MOTD(&'a [u8]), /// 376 RPL_ENDOFMOTD /// ":End of MOTD command" /// /// - When responding to the MOTD message and the MOTD file /// is found, the file is displayed line by line, with /// each line no longer than 80 characters, using /// RPL_MOTD format replies. These MUST be surrounded /// by a RPL_MOTDSTART (before the RPL_MOTDs) and an /// RPL_ENDOFMOTD (after). /// RPL_ENDOFMOTD(&'a [u8]), /// 381 RPL_YOUREOPER /// ":You are now an IRC operator" /// /// - RPL_YOUREOPER is sent back to a client which has /// just successfully issued an OPER message and gained /// operator status. /// RPL_YOUREOPER(&'a [u8]), /// 382 RPL_REHASHING /// " :Rehashing" /// /// - If the REHASH option is used and an operator sends /// a REHASH message, an RPL_REHASHING is sent back to /// the operator. /// RPL_REHASHING(&'a [u8]), /// 383 RPL_YOURESERVICE /// "You are service " /// /// - Sent by the server to a service upon successful /// registration. /// RPL_YOURESERVICE(&'a [u8]), /// 391 RPL_TIME /// " :" /// /// - When replying to the TIME message, a server MUST send /// the reply using the RPL_TIME format above. The string /// showing the time need only contain the correct day and /// time there. There is no further requirement for the /// time string. /// RPL_TIME(&'a [u8]), /// 392 RPL_USERSSTART /// ":UserID Terminal Host" RPL_USERSSTART(&'a [u8]), /// 393 RPL_USERS /// ": " RPL_USERS(&'a [u8]), /// 394 RPL_ENDOFUSERS /// ":End of users" RPL_ENDOFUSERS(&'a [u8]), /// 395 RPL_NOUSERS /// ":Nobody logged in" /// /// - If the USERS message is handled by a server, the /// replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and /// RPL_NOUSERS are used. RPL_USERSSTART MUST be sent /// first, following by either a sequence of RPL_USERS /// or a single RPL_NOUSER. Following this is /// RPL_ENDOFUSERS. /// RPL_NOUSERS(&'a [u8]), /// 200 RPL_TRACELINK /// "Link /// V /// /// " RPL_TRACELINK(&'a [u8]), /// 201 RPL_TRACECONNECTING /// "Try. " RPL_TRACECONNECTING(&'a [u8]), /// 202 RPL_TRACEHANDSHAKE /// "H.S. " RPL_TRACEHANDSHAKE(&'a [u8]), /// 203 RPL_TRACEUNKNOWN /// "???? []" RPL_TRACEUNKNOWN(&'a [u8]), /// 204 RPL_TRACEOPERATOR /// "Oper " RPL_TRACEOPERATOR(&'a [u8]), /// 205 RPL_TRACEUSER /// "User " RPL_TRACEUSER(&'a [u8]), /// 206 RPL_TRACESERVER /// "Serv S C /// @ V" RPL_TRACESERVER(&'a [u8]), /// 207 RPL_TRACESERVICE /// "Service " RPL_TRACESERVICE(&'a [u8]), /// 208 RPL_TRACENEWTYPE /// " 0 " RPL_TRACENEWTYPE(&'a [u8]), /// 209 RPL_TRACECLASS /// "Class " RPL_TRACECLASS(&'a [u8]), /// 210 RPL_TRACERECONNECT /// Unused. RPL_TRACERECONNECT(&'a [u8]), /// 261 RPL_TRACELOG /// "File " RPL_TRACELOG(&'a [u8]), /// 262 RPL_TRACEEND /// " :End of TRACE" /// /// - The RPL_TRACE* are all returned by the server in /// response to the TRACE message. How many are /// returned is dependent on the TRACE message and /// whether it was sent by an operator or not. There /// is no predefined order for which occurs first. /// Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and /// RPL_TRACEHANDSHAKE are all used for connections /// which have not been fully established and are either /// unknown, still attempting to connect or in the /// process of completing the 'server handshake'. /// RPL_TRACELINK is sent by any server which handles /// a TRACE message and has to pass it on to another /// server. The list of RPL_TRACELINKs sent in /// response to a TRACE command traversing the IRC /// network should reflect the actual connectivity of /// the servers themselves along that path. /// /// RPL_TRACENEWTYPE is to be used for any connection /// which does not fit in the other categories but is /// being displayed anyway. /// RPL_TRACEEND is sent to indicate the end of the list. /// RPL_TRACEEND(&'a [u8]), /// 211 RPL_STATSLINKINFO /// " /// ///