aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml3
-rw-r--r--src/client.rs175
-rw-r--r--src/command.rs523
-rw-r--r--src/lib.rs11
-rw-r--r--src/message.rs218
-rw-r--r--src/reply.rs812
-rw-r--r--src/text.rs196
7 files changed, 1046 insertions, 892 deletions
diff --git a/Cargo.toml b/Cargo.toml
index b268304..03ef4af 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,8 @@ log = "^0.3"
regex = "^0.1"
regex_macros = "^0.1"
openssl = "^0.6"
-carboxyl = "^0.1"
+encoding = "^0.2"
+linear-map = "^0.0"
[features]
lints = ["clippy"]
diff --git a/src/client.rs b/src/client.rs
index a154fba..690ef30 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -11,13 +11,12 @@ use std::sync::{ Arc, RwLock };
use std::mem;
use std::cell::UnsafeCell;
-use carboxyl::{ Stream, Sink };
-
use message::Message;
use command::Command;
use command::Command::*;
use reply::Reply;
use event::Event;
+use text::*;
use ::{ DEBUG, Result, IrscError };
use openssl::ssl::{ Ssl, SslContext, SslMethod, SslStream };
@@ -53,60 +52,14 @@ impl Read for StreamKind {
}
}
-pub trait Client {
- fn send_message(&mut self, msg: Message) -> Result<()>;
- fn join(&mut self, channel: &str, password: Option<&str>) -> Result<()> {
- self.send_message(JOIN(vec![channel.into()], password.iter().map(|&p| p.into()).collect()).to_message())
- }
-
- fn msg(&mut self, to: &str, message: &str) -> Result<()> {
- self.send_message(PRIVMSG(to.into(), message.into()).to_message())
- }
-
- fn msg_many(&mut self, to: &str, message: &[&str]) -> Result<()> {
- for m in message {
- self.msg(to, m);
- }
- Result(Ok(()))
- }
- fn msg_word_wrap(&mut self, to: &str, message: &str, limit: u16) -> Result<()> {
- let mut line = String::new();
- for word in message.split_whitespace() {
- if line.len() + word.len() < limit as usize {
- line.push_str(" ");
- line.push_str(word);
- } else {
- debug!("Sending {}", line);
- self.msg(to, &line);
- line.clear();
- }
- }
- self.msg(to, &line)
- }
-
- fn register(&mut self, nick: &str, user: &str, desc: &str, pass: Option<&str>) -> Result<()> {
- Result(if let Some(pass) = pass {
- self.send_message(PASS(pass.into()).to_message()).inner()
- } else { Ok(()) }
- .and_then(|_| self.send_message(NICK(nick.into()).to_message()).inner())
- .and_then(|_| self.send_message(USER(user.into(), Borrowed("0"), Borrowed("*"), desc.into()).to_message()).inner())
- )
- }
-
-}
-
-pub struct OwnedClient {
+pub struct Client {
stream: Option<StreamKind>,
- sink: Sink<Message>
}
-impl OwnedClient {
- pub fn new() -> OwnedClient {
- OwnedClient {
- stream: None,
- sink: Sink::new()
- }
+impl Client {
+ pub fn new() -> Client {
+ Client { stream: None }
}
fn handle_event(&mut self, msg: &Message) {
@@ -146,25 +99,27 @@ impl OwnedClient {
}
#[inline]
- fn send_raw(&mut self, s: &str) -> Result<()> {
- info!(">> {}", s);
- if DEBUG && s.len() > 512 {
- panic!("Message too long, kittens will die if this runs in release mode. Msg: {}", s)
+ fn send_raw(&mut self, s: &[u8]) -> Result<()> {
+ if DEBUG && s.len() > 1024 {
+ panic!("Message too long, kittens will die if this runs in release mode.")
}
Result(self.stream.as_mut()
.ok_or(IrscError::NotConnected)
- .and_then(|mut stream| stream.write_all(s.as_bytes())
+ .and_then(|mut stream| stream.write_all(s)
.and_then(|_| stream.flush())
.map_err(IrscError::Io)))
}
+ fn send_message(&mut self, msg: Message) -> Result<()> {
+ self.send_raw(msg.bytes())
+ }
pub fn send(&mut self, cmd: Command) -> Result<()> {
self.send_message(cmd.to_message())
}
- pub fn listen_with_callback<F>(&mut self, on_event: F) -> Result<()>
+ pub fn listen<F>(&mut self, on_event: F) -> Result<()>
where F: Fn(&mut Client, &Message, Option<Event>) {
let reader = BufReader::new(match self.stream {
Some(StreamKind::Plain(ref s)) => StreamKind::Plain((*s).try_clone().unwrap()),
@@ -173,7 +128,7 @@ impl OwnedClient {
});
for raw_line in reader.lines() {
- let line = raw_line.as_ref().unwrap().parse();
+ let line = Message::parse(raw_line.as_ref().unwrap().as_bytes());
info!("<< {}", raw_line.unwrap());
if let Ok(msg) = line {
@@ -193,88 +148,42 @@ impl OwnedClient {
Result(Ok(()))
}
- #[allow(mutable_transmutes)]
- fn listen_with_events(&self) -> Result<()> {
- let mut s: &mut OwnedClient = unsafe { mem::transmute(self) };
- let reader = BufReader::new(match self.stream {
- Some(StreamKind::Plain(ref s)) => StreamKind::Plain((*s).try_clone().unwrap()),
- Some(StreamKind::Ssl(ref s)) => StreamKind::Ssl((*s).try_clone().unwrap()),
- None => return Result(Err(IrscError::NotConnected))
- });
-
- for raw_line in reader.lines() {
- let line = raw_line.as_ref().unwrap().parse();
- info!("<< {}", raw_line.unwrap());
-
- if let Ok(msg) = line {
- s.handle_event(&msg);
- self.sink.send(msg);
- }
- }
- Result(Ok(()))
- }
-
- pub fn into_shared(self) -> SharedClient {
- SharedClient {
- client: Arc::new(OwnedClientCell(UnsafeCell::new(self))),
- }
+ fn join(&mut self, channel: &str, password: Option<&str>) -> Result<()> {
+ self.send_message(JOIN(vec![channel.into()], password.iter().map(|&p| p.into()).collect()).to_message())
}
- pub fn messages(&self) -> Stream<Message> { self.sink.stream() }
-}
-
-struct OwnedClientCell(UnsafeCell<OwnedClient>);
-unsafe impl Sync for OwnedClientCell {}
-
-impl Client for OwnedClient {
- fn send_message(&mut self, msg: Message) -> Result<()> {
- self.send_raw(&msg.to_string())
+ fn msg(&mut self, to: &str, message: &str) -> Result<()> {
+ self.send_message(PRIVMSG(to.into(), message.into()).to_message())
}
-}
-
-#[derive(Clone)]
-pub struct SharedClient {
- client: Arc<OwnedClientCell>,
-}
-impl SharedClient {
- pub fn messages(&self) -> Stream<(SharedClient, Message)> {
- let cl = SharedClient { client: self.client.clone() };
- unsafe { &*self.client.0.get() }.messages()
- .map(move |m| (cl.clone(), m))
+ fn msg_many(&mut self, to: &str, message: &[&str]) -> Result<()> {
+ for m in message {
+ self.msg(to, m);
+ }
+ Result(Ok(()))
}
- pub fn events(&self) -> Stream<(SharedClient, Message, Event<'static>)> {
- self.messages().filter_map(|(cl, msg)| match Command::from_message(&msg) {
- Some(m) => Some((cl, msg.clone(), Event::Command(m.clone()).to_static())),
- None => match Reply::from_message(&msg) {
- Some(r) => Some((cl, msg.clone(), Event::Reply(r).to_static())),
- None => None
+ fn msg_word_wrap(&mut self, to: &str, message: &str, limit: u16) -> Result<()> {
+ let mut line = String::new();
+ for word in message.split_whitespace() {
+ if line.len() + word.len() < limit as usize {
+ line.push_str(" ");
+ line.push_str(word);
+ } else {
+ debug!("Sending {}", line);
+ self.msg(to, &line);
+ line.clear();
}
- })
- }
-
- pub fn listen_with_events(&mut self) -> Result<()> {
- unsafe { &*self.client.0.get() }.listen_with_events()
- }
-
- pub fn commands(&self) -> Stream<(SharedClient, Message, Command<'static>)> {
- self.messages().filter_map(|(cl, msg)| match Command::from_message(&msg) {
- Some(m) => Some((cl, msg.clone(), m.to_static())),
- None => None
- })
- }
-
- pub fn replies(&self) -> Stream<(SharedClient, Message, Reply<'static>)> {
- self.messages().filter_map(|(cl, msg)| match Reply::from_message(&msg) {
- Some(m) => Some((cl, msg.clone(), m.to_static())),
- None => None
- })
+ }
+ self.msg(to, &line)
}
-}
-impl Client for SharedClient {
- fn send_message(&mut self, msg: Message) -> Result<()> {
- unsafe { &mut *self.client.0.get() }.send_raw(&msg.to_string())
+ fn register(&mut self, nick: &str, user: &str, desc: &str, pass: Option<&str>) -> Result<()> {
+ Result(if let Some(pass) = pass {
+ self.send_message(PASS(pass.into()).to_message()).inner()
+ } else { Ok(()) }
+ .and_then(|_| self.send_message(NICK(nick.into()).to_message()).inner())
+ .and_then(|_| self.send_message(USER(user.into(), tsu("0"), tsu("*"), desc.into()).to_message()).inner())
+ )
}
}
diff --git a/src/command.rs b/src/command.rs
index 1043a43..5f76398 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -4,7 +4,8 @@ use std::borrow::{ Cow, IntoCow, Borrow, ToOwned };
use std::borrow::Cow::*;
use std::iter::Extend;
-use message::{ Message, MsgType };
+use message::Message;
+use text::{ Text, TextSlice };
pub type CS<'a> = Cow<'a, str>;
@@ -20,89 +21,241 @@ pub type CS<'a> = Cow<'a, str>;
//
// Please don't cry.
-#[derive(Debug, Hash, Clone, PartialEq, Eq)]
-pub enum Command<'a> {
- /// ```text
- /// 3.1.1 Password message
- ///
- /// Command: PASS
- /// Parameters: <password>
- ///
- /// The PASS command is used to set a 'connection password'. The
- /// optional password can and MUST be set before any attempt to register
- /// the connection is made. Currently this requires that user send a
- /// PASS command before sending the NICK/USER combination.
- ///
- /// Numeric Replies:
- ///
- /// ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
- ///
- /// Example:
- ///
- /// PASS secretpasswordhere
- /// ```
- PASS(CS<'a>),
+macro_rules! commands {
+ ($( $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)]
+ pub enum Command<'a> {
+ $(
+ #[$doc]
+ $name($($borrowed_items),*)
+ ),+
+ }
- /// ```text
- /// 3.1.2 Nick message
- ///
- /// Command: NICK
- /// Parameters: <nickname>
- ///
- /// NICK command is used to give user a nickname or change the existing
- /// one.
- ///
- /// Numeric Replies:
- ///
- /// ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME
- /// ERR_NICKNAMEINUSE ERR_NICKCOLLISION
- /// ERR_UNAVAILRESOURCE ERR_RESTRICTED
- ///
- /// Examples:
- ///
- /// NICK Wiz ; Introducing new nick "Wiz" if session is
- /// still unregistered, or user changing his
- /// nickname to "Wiz"
- ///
- /// :WiZ!jto@tolsun.oulu.fi NICK Kilroy
- /// ; Server telling that WiZ changed his
- /// nickname to Kilroy.
- /// ```
- NICK(CS<'a>),
+ #[allow(non_camel_case_types)]
+ #[derive(Debug, Hash, Clone, PartialEq)]
+ pub enum OwnedCommand {
+ $(
+ #[$doc]
+ $name($($owned_items),*)
+ ),+
+ }
- /// ```text
- /// 3.1.3 User message
- ///
- /// Command: USER
- /// Parameters: <user> <mode> <unused> <realname>
- ///
- /// The USER command is used at the beginning of connection to specify
- /// the username, hostname and realname of a new user.
- ///
- /// The <mode> parameter should be a numeric, and can be used to
- /// automatically set user modes when registering with the server. This
- /// parameter is a bitmask, with only 2 bits having any signification: if
- /// the bit 2 is set, the user mode 'w' will be set and if the bit 3 is
- /// set, the user mode 'i' will be set. (See Section 3.1.5 "User
- /// Modes").
- ///
- /// The <realname> may contain space characters.
- ///
- /// Numeric Replies:
- ///
- /// ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
- ///
- /// Example:
- ///
- /// USER guest 0 * :Ronnie Reagan ; User registering themselves with a
- /// username of "guest" and real name
- /// "Ronnie Reagan".
- ///
- /// USER guest 8 * :Ronnie Reagan ; User registering themselves with a
- /// username of "guest" and real name
- /// "Ronnie Reagan", and asking to be set
- /// invisible.
- /// ```
+ impl<'a> Command<'a> {
+ pub fn to_owned(self) -> OwnedCommand {
+ match self {
+ $(
+ Command::$name($($to_names),*) => OwnedCommand::$name($($to_exprs),*)
+ ),+
+ }
+ }
+
+ pub fn from_message(msg: &'a Message) -> Option<Command<'a>> {
+ use Command::*;
+ match msg.command() {
+ $(
+ $id => msg.last().map(|&e| $name(e))
+ ),+
+ }
+ }
+
+ pub fn to_message(&self) -> Message {
+ use Command::*;
+ match self {
+ $(
+ &$name(ref s) => Message::format(None, $id, Vec::new(), s)
+ ),+
+ }
+ }
+ }
+ )
+}
+
+commands! {
+ PASS {
+ "PASS", doc = r#"```text
+ 3.1.1 Password message
+
+ Command: PASS
+ Parameters: <password>
+
+ The PASS command is used to set a 'connection password'. The
+ optional password can and MUST be set before any attempt to register
+ the connection is made. Currently this requires that user send a
+ PASS command before sending the NICK/USER combination.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Example:
+
+ PASS secretpasswordhere
+ ```"#
+ b TextSlice<'a>
+ o Text
+ t t => t.into()
+ },
+ NICK {
+ "NICK", doc = r#"```text
+ 3.1.2 Nick message
+
+ Command: NICK
+ Parameters: <nickname>
+
+ NICK command is used to give user a nickname or change the existing
+ one.
+
+ Numeric Replies:
+
+ ERR_NONICKNAMEGIVEN ERR_ERRONEUSNICKNAME
+ ERR_NICKNAMEINUSE ERR_NICKCOLLISION
+ ERR_UNAVAILRESOURCE ERR_RESTRICTED
+
+ Examples:
+
+ NICK Wiz ; Introducing new nick "Wiz" if session is
+ still unregistered, or user changing his
+ nickname to "Wiz"
+
+ :WiZ!jto@tolsun.oulu.fi NICK Kilroy
+ ; Server telling that WiZ changed his
+ nickname to Kilroy.
+ ```"#
+ b TextSlice<'a>
+ o Text
+ t t => t.into()
+ },
+ USER {
+ "USER", doc = r#"```text
+ 3.1.3 User message
+
+ Command: USER
+ Parameters: <user> <mode> <unused> <realname>
+
+ The USER command is used at the beginning of connection to specify
+ the username, hostname and realname of a new user.
+
+ The <mode> parameter should be a numeric, and can be used to
+ automatically set user modes when registering with the server. This
+ parameter is a bitmask, with only 2 bits having any signification: if
+ the bit 2 is set, the user mode 'w' will be set and if the bit 3 is
+ set, the user mode 'i' will be set. (See Section 3.1.5 "User
+ Modes").
+
+ The <realname> may contain space characters.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_ALREADYREGISTRED
+
+ Example:
+
+ USER guest 0 * :Ronnie Reagan ; User registering themselves with a
+ username of "guest" and real name
+ "Ronnie Reagan".
+
+ USER guest 8 * :Ronnie Reagan ; User registering themselves with a
+ username of "guest" and real name
+ "Ronnie Reagan", and asking to be set
+ invisible.
+ ```"#
+ b TextSlice<'a>, TextSlice<'a>, TextSlice<'a>, TextSlice<'a>
+ o Text, Text, Text, Text
+ t r, s, t, u => r.into(), s.into(), t.into(), u.into()
+ },
+ JOIN {
+ "JOIN", doc = r#"```text
+ 3.2.1 Join message
+
+ Command: JOIN
+ Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
+ / "0"
+
+ The JOIN command is used by a user to request to start listening to
+ the specific channel. Servers MUST be able to parse arguments in the
+ form of a list of target, but SHOULD NOT use lists when sending JOIN
+ messages to clients.
+
+ Once a user has joined a channel, he receives information about
+ all commands his server receives affecting the channel. This
+ includes JOIN, MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE.
+ This allows channel members to keep track of the other channel
+ members, as well as channel modes.
+
+ If a JOIN is successful, the user receives a JOIN message as
+ confirmation and is then sent the channel's topic (using RPL_TOPIC) and
+ the list of users who are on the channel (using RPL_NAMREPLY), which
+ MUST include the user joining.
+
+ Note that this message accepts a special argument ("0"), which is
+ a special request to leave all channels the user is currently a member
+ of. The server will process this message as if the user had sent
+ a PART command (See Section 3.2.2) for each channel he is a member
+ of.
+
+ Numeric Replies:
+
+ ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN
+ ERR_INVITEONLYCHAN ERR_BADCHANNELKEY
+ ERR_CHANNELISFULL ERR_BADCHANMASK
+ ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS
+ ERR_TOOMANYTARGETS ERR_UNAVAILRESOURCE
+ RPL_TOPIC
+
+ Examples:
+
+ JOIN #foobar ; Command to join channel #foobar.
+
+ JOIN &foo fubar ; Command to join channel &foo using
+ key "fubar".
+
+ JOIN #foo,&bar fubar ; Command to join channel #foo using
+ key "fubar" and &bar using no key.
+
+ JOIN #foo,#bar fubar,foobar ; Command to join channel #foo using
+ key "fubar", and channel #bar using
+ key "foobar".
+
+ JOIN #foo,#bar ; Command to join channels #foo and
+ #bar.
+
+ JOIN 0 ; Leave all currently joined
+ channels.
+
+ :WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone ; JOIN message from WiZ
+ on channel #Twilight_zone
+ ```"#
+ b Vec<TextSlice<'a>>, Vec<TextSlice<'a>>
+ o Vec<Text>, Vec<Text>
+ t c, p => c.into_iter().map(Into::into).collect(),
+ p.into_iter().map(Into::into).collect()
+ },
+ PRIVMSG {
+ "PRIVMSG", doc = ""
+ b TextSlice<'a>, TextSlice<'a>
+ o Text, Text
+ t target, content => target.into(), content.into()
+ },
+ PING {
+ "PING", doc = ""
+ b TextSlice<'a>, Option<TextSlice<'a>>
+ o Text, Option<Text>
+ t s1, s2 => s1.into(), s2.map(Into::into)
+ },
+ PONG {
+ "PONG", doc = ""
+ b TextSlice<'a>, Option<TextSlice<'a>>
+ o Text, Option<Text>
+ t s1, s2 => s1.into(), s2.into()
+ }
+}
+/*
USER(CS<'a>, CS<'a>, CS<'a>, CS<'a>),
/// ```text
@@ -288,68 +441,6 @@ pub enum Command<'a> {
/// ```
SQUIT(CS<'a>, CS<'a>),
- /// ```text
- /// 3.2.1 Join message
- ///
- /// Command: JOIN
- /// Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
- /// / "0"
- ///
- /// The JOIN command is used by a user to request to start listening to
- /// the specific channel. Servers MUST be able to parse arguments in the
- /// form of a list of target, but SHOULD NOT use lists when sending JOIN
- /// messages to clients.
- ///
- /// Once a user has joined a channel, he receives information about
- /// all commands his server receives affecting the channel. This
- /// includes JOIN, MODE, KICK, PART, QUIT and of course PRIVMSG/NOTICE.
- /// This allows channel members to keep track of the other channel
- /// members, as well as channel modes.
- ///
- /// If a JOIN is successful, the user receives a JOIN message as
- /// confirmation and is then sent the channel's topic (using RPL_TOPIC) and
- /// the list of users who are on the channel (using RPL_NAMREPLY), which
- /// MUST include the user joining.
- ///
- /// Note that this message accepts a special argument ("0"), which is
- /// a special request to leave all channels the user is currently a member
- /// of. The server will process this message as if the user had sent
- /// a PART command (See Section 3.2.2) for each channel he is a member
- /// of.
- ///
- /// Numeric Replies:
- ///
- /// ERR_NEEDMOREPARAMS ERR_BANNEDFROMCHAN
- /// ERR_INVITEONLYCHAN ERR_BADCHANNELKEY
- /// ERR_CHANNELISFULL ERR_BADCHANMASK
- /// ERR_NOSUCHCHANNEL ERR_TOOMANYCHANNELS
- /// ERR_TOOMANYTARGETS ERR_UNAVAILRESOURCE
- /// RPL_TOPIC
- ///
- /// Examples:
- ///
- /// JOIN #foobar ; Command to join channel #foobar.
- ///
- /// JOIN &foo fubar ; Command to join channel &foo using
- /// key "fubar".
- ///
- /// JOIN #foo,&bar fubar ; Command to join channel #foo using
- /// key "fubar" and &bar using no key.
- ///
- /// JOIN #foo,#bar fubar,foobar ; Command to join channel #foo using
- /// key "fubar", and channel #bar using
- /// key "foobar".
- ///
- /// JOIN #foo,#bar ; Command to join channels #foo and
- /// #bar.
- ///
- /// JOIN 0 ; Leave all currently joined
- /// channels.
- ///
- /// :WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone ; JOIN message from WiZ
- /// on channel #Twilight_zone
- /// ```
- JOIN(Vec<CS<'a>>, Vec<CS<'a>>),
/// ```text
/// 3.2.2 Part message
@@ -1596,31 +1687,31 @@ pub enum Command<'a> {
match self {
&PASS(ref pw) => PASS(pw.to_owned().clone()),
/*&NICK(ref nick) =>
- Message::format(None, Borrowed("NICK"), vec![], Some(nick.clone()), MsgType::Irc),
+ Message::format(None, Borrowed("NICK"), vec![], Some(nick.clone())),
&USER(ref user, ref mode, ref unused, ref realname) =>
Message::format(None, Borrowed("USER"),
vec![user.clone(), mode.clone(), unused.clone()],
- Some(realname.clone()), MsgType::Irc),
+ Some(realname.clone())),
&OPER(ref name, ref pw) =>
Message::format(None, Borrowed("OPER"),
- vec![name.clone(), pw.clone()], None, MsgType::Irc),
+ vec![name.clone(), pw.clone()], None),
&UMODE(ref mode) =>
- Message::format(None, Borrowed("MODE"), vec![], Some(mode.clone()), MsgType::Irc),
+ Message::format(None, Borrowed("MODE"), vec![], Some(mode.clone())),
&SERVICE(ref nick, ref reserved, ref distribution, ref type_, ref reserved2, ref info) =>
Message::format(None, Borrowed("SERVICE"),
vec![nick.clone(), reserved.clone(), distribution.clone(),
- type_.clone(), reserved2.clone()], Some(info.clone()), MsgType::Irc),
+ type_.clone(), reserved2.clone()], Some(info.clone())),
&QUIT(ref msg) =>
- Message::format(None, Borrowed("QUIT"), vec![], msg.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("QUIT"), vec![], msg.clone()),
&SQUIT(ref server, ref comment) =>
Message::format(None, Borrowed("SQUIT"),
- vec![server.clone()], Some(comment.clone()), MsgType::Irc),
+ vec![server.clone()], Some(comment.clone())),
&JOIN(ref ch, ref pw) =>
Message::format(None, Borrowed("JOIN"),
- vec![Owned(ch.connect(",")), Owned(pw.connect(","))], None, MsgType::Irc),
+ vec![Owned(ch.connect(",")), Owned(pw.connect(","))], None),
&PART(ref ch, ref reason) =>
Message::format(None, Borrowed("PART"),
- vec![Owned(ch.connect(","))], reason.clone(), MsgType::Irc),
+ vec![Owned(ch.connect(","))], reason.clone()),
&MODE(ref channel, ref modes) =>
// Screw this, folding will have to do.
Message::format(None, Borrowed("MODE"),
@@ -1628,98 +1719,98 @@ pub enum Command<'a> {
v.push(a.clone());
v.push(b.clone());
v
- }), None, MsgType::Irc),
+ }), None),
&TOPIC(ref channel, ref topic) =>
Message::format(None, Borrowed("TOPIC"),
- vec![channel.clone()], topic.clone(), MsgType::Irc),
+ vec![channel.clone()], topic.clone()),
&NAMES(ref ch, ref target) =>
Message::format(None, Borrowed("NAMES"),
- vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc),
+ vec![Owned(ch.connect(","))], target.clone()),
&LIST(ref ch, ref target) =>
Message::format(None, Borrowed("LIST"),
- vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc),
+ vec![Owned(ch.connect(","))], target.clone()),
&INVITE(ref nick, ref channel) =>
Message::format(None, Borrowed("INVITE"),
- vec![nick.clone()], Some(channel.clone()), MsgType::Irc),
+ vec![nick.clone()], Some(channel.clone())),
&KICK(ref ch, ref users, ref comment) =>
Message::format(None, Borrowed("KICK"),
vec![Owned(ch.connect(",")), Owned(users.connect(","))],
- comment.clone(), MsgType::Irc),
+ comment.clone()),
&PRIVMSG(ref target, ref msg) =>
Message::format(None, Borrowed("PRIVMSG"),
- vec![target.clone()], Some(msg.clone()), MsgType::Irc),
+ vec![target.clone()], Some(msg.clone())),
&NOTICE(ref target, ref text) =>
Message::format(None, Borrowed("NOTICE"),
- vec![target.clone()], Some(text.clone()), MsgType::Irc),
+ vec![target.clone()], Some(text.clone())),
&MOTD(ref target) =>
- Message::format(None, Borrowed("MOTD"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("MOTD"), vec![], target.clone()),
&LUSERS(ref lu) =>
Message::format(None, Borrowed("LUSERS"),
lu.as_ref().map(|&(ref mask, _)| vec![mask.clone()]).unwrap_or(vec![]),
- lu.as_ref().and_then(|&(_, ref target)| target.clone()), MsgType::Irc),
+ lu.as_ref().and_then(|&(_, ref target)| target.clone())),
&VERSION(ref target) =>
- Message::format(None, Borrowed("VERSION"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("VERSION"), vec![], target.clone()),
&STATS(ref st) =>
Message::format(None, Borrowed("STATS"),
st.as_ref().map(|&(ref query, _)| vec![query.clone()]).unwrap_or(vec![]),
- st.as_ref().and_then(|&(_, ref target)| target.clone()), MsgType::Irc),
+ st.as_ref().and_then(|&(_, ref target)| target.clone())),
&LINKS(ref l) =>
Message::format(None, Borrowed("LINKS"),
l.as_ref().map(|&(ref remote, ref mask)| if remote.is_some() {
vec![remote.clone().unwrap(), mask.clone()] } else { vec![mask.clone()] }).unwrap_or(vec![]),
- None, MsgType::Irc),
+ None),
&TIME(ref target) =>
- Message::format(None, Borrowed("TIME"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("TIME"), vec![], target.clone()),
&CONNECT(ref server, ref port, ref remote) =>
Message::format(None, Borrowed("CONNECT"),
- vec![server.clone(), Owned(format!("{}", port))], remote.clone(), MsgType::Irc),
+ vec![server.clone(), Owned(format!("{}", port))], remote.clone()),
&TRACE(ref target) =>
- Message::format(None, Borrowed("TRACE"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("TRACE"), vec![], target.clone()),
&ADMIN(ref target) =>
- Message::format(None, Borrowed("ADMIN"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("ADMIN"), vec![], target.clone()),
&INFO(ref target) =>
- Message::format(None, Borrowed("INFO"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("INFO"), vec![], target.clone()),
&SERVLIST(ref sl) =>
Message::format(None, Borrowed("SERVLIST"),
sl.as_ref().map(|&(ref mask, ref target)| target.as_ref()
.map(|t| vec![mask.clone(), t.clone()])
.unwrap_or_else(|| vec![mask.clone()]))
- .unwrap_or(vec![]), None, MsgType::Irc),
+ .unwrap_or(vec![]), None),
&SQUERY(ref name, ref text) =>
Message::format(None, Borrowed("SQUERY"),
- vec![name.clone()], Some(text.clone()), MsgType::Irc),
+ vec![name.clone()], Some(text.clone())),
&WHO(ref mask, o) =>
Message::format(None, Borrowed("WHO"),
match (mask, o) {
(&Some(ref m), true) => vec![m.clone(), Borrowed("o")],
(&Some(ref m), false) => vec![m.clone()],
(&None, _) => vec![]
- }, None, MsgType::Irc),
+ }, None),
&WHOIS(ref target, ref masks) =>
Message::format(None, Borrowed("WHOIS"),
target.as_ref().map(|t| vec![t.clone(), Owned(masks.connect(","))])
- .unwrap_or_else(|| vec![Owned(masks.connect(","))]), None, MsgType::Irc),
+ .unwrap_or_else(|| vec![Owned(masks.connect(","))]), None),
&WHOWAS(ref nick, ref count) =>
Message::format(None, Borrowed("WHOWAS"), match count {
&Some((ref c, Some(ref t))) => vec![Owned(nick.connect(",")), c.clone(), t.clone()],
&Some((ref c, None)) => vec![Owned(nick.connect(",")), c.clone()],
&None => vec![Owned(nick.connect(","))]
- }, None, MsgType::Irc),
+ }, None),
&PING(ref s1, ref s2) =>
- Message::format(None, Borrowed("PING"), vec![s1.clone()], s2.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("PING"), vec![s1.clone()], s2.clone()),
&PONG(ref s1, ref s2) =>
- Message::format(None, Borrowed("PONG"), vec![s1.clone()], s2.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("PONG"), vec![s1.clone()], s2.clone()),
*/ /*&Command::PING(ref server1, ref server2) => {
let mut c = Vec::new();
c.push(server1.clone());
if let &Some(ref s) = server2 { c.push(s.clone()) }
- Message::format(None, "PING", c, None, MsgType::Irc)
+ Message::format(None, "PING", c, None)
},
&Command::PONG(ref server1, ref server2) => {
let mut c = Vec::new();
c.push(server1.clone());
if let &Some(ref s) = server2 { c.push(s.clone()) }
- Message::format(None, "PONG", c, None, MsgType::Irc)
+ Message::format(None, "PONG", c, None)
},*/
_ => unimplemented!()
}
@@ -1773,33 +1864,33 @@ impl<'a> Command<'a> {
use self::Command::*;
match self {
&PASS(ref pw) =>
- Message::format(None, Borrowed("PASS"), vec![], Some(pw.clone()), MsgType::Irc),
+ Message::format(None, Borrowed("PASS"), vec![], Some(pw.clone())),
&NICK(ref nick) =>
- Message::format(None, Borrowed("NICK"), vec![], Some(nick.clone()), MsgType::Irc),
+ Message::format(None, Borrowed("NICK"), vec![], Some(nick.clone())),
&USER(ref user, ref mode, ref unused, ref realname) =>
Message::format(None, Borrowed("USER"),
vec![user.clone(), mode.clone(), unused.clone()],
- Some(realname.clone()), MsgType::Irc),
+ Some(realname.clone())),
&OPER(ref name, ref pw) =>
Message::format(None, Borrowed("OPER"),
- vec![name.clone(), pw.clone()], None, MsgType::Irc),
+ vec![name.clone(), pw.clone()], None),
&UMODE(ref mode) =>
- Message::format(None, Borrowed("MODE"), vec![], Some(mode.clone()), MsgType::Irc),
+ Message::format(None, Borrowed("MODE"), vec![], Some(mode.clone())),
&SERVICE(ref nick, ref reserved, ref distribution, ref type_, ref reserved2, ref info) =>
Message::format(None, Borrowed("SERVICE"),
vec![nick.clone(), reserved.clone(), distribution.clone(),
- type_.clone(), reserved2.clone()], Some(info.clone()), MsgType::Irc),
+ type_.clone(), reserved2.clone()], Some(info.clone())),
&QUIT(ref msg) =>
- Message::format(None, Borrowed("QUIT"), vec![], msg.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("QUIT"), vec![], msg.clone()),
&SQUIT(ref server, ref comment) =>
Message::format(None, Borrowed("SQUIT"),
- vec![server.clone()], Some(comment.clone()), MsgType::Irc),
+ vec![server.clone()], Some(comment.clone())),
&JOIN(ref ch, ref pw) =>
Message::format(None, Borrowed("JOIN"),
- vec![Owned(ch.connect(",")), Owned(pw.connect(","))], None, MsgType::Irc),
+ vec![Owned(ch.connect(",")), Owned(pw.connect(","))], None),
&PART(ref ch, ref reason) =>
Message::format(None, Borrowed("PART"),
- vec![Owned(ch.connect(","))], reason.clone(), MsgType::Irc),
+ vec![Owned(ch.connect(","))], reason.clone()),
&MODE(ref channel, ref modes) =>
// Screw this, folding will have to do.
Message::format(None, Borrowed("MODE"),
@@ -1807,87 +1898,87 @@ impl<'a> Command<'a> {
v.push(a.clone());
v.push(b.clone());
v
- }), None, MsgType::Irc),
+ }), None),
&TOPIC(ref channel, ref topic) =>
Message::format(None, Borrowed("TOPIC"),
- vec![channel.clone()], topic.clone(), MsgType::Irc),
+ vec![channel.clone()], topic.clone()),
&NAMES(ref ch, ref target) =>
Message::format(None, Borrowed("NAMES"),
- vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc),
+ vec![Owned(ch.connect(","))], target.clone()),
&LIST(ref ch, ref target) =>
Message::format(None, Borrowed("LIST"),
- vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc),
+ vec![Owned(ch.connect(","))], target.clone()),
&INVITE(ref nick, ref channel) =>
Message::format(None, Borrowed("INVITE"),
- vec![nick.clone()], Some(channel.clone()), MsgType::Irc),
+ vec![nick.clone()], Some(channel.clone())),
&KICK(ref ch, ref users, ref comment) =>
Message::format(None, Borrowed("KICK"),
vec![Owned(ch.connect(",")), Owned(users.connect(","))],
- comment.clone(), MsgType::Irc),
+ comment.clone()),
&PRIVMSG(ref target, ref msg) =>
Message::format(None, Borrowed("PRIVMSG"),
- vec![target.clone()], Some(msg.clone()), MsgType::Irc),
+ vec![target.clone()], Some(msg.clone())),
&NOTICE(ref target, ref text) =>
Message::format(None, Borrowed("NOTICE"),
- vec![target.clone()], Some(text.clone()), MsgType::Irc),
+ vec![target.clone()], Some(text.clone())),
&MOTD(ref target) =>
- Message::format(None, Borrowed("MOTD"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("MOTD"), vec![], target.clone()),
&LUSERS(ref lu) =>
Message::format(None, Borrowed("LUSERS"),
lu.as_ref().map(|&(ref mask, _)| vec![mask.clone()]).unwrap_or(vec![]),
- lu.as_ref().and_then(|&(_, ref target)| target.clone()), MsgType::Irc),
+ lu.as_ref().and_then(|&(_, ref target)| target.clone())),
&VERSION(ref target) =>
- Message::format(None, Borrowed("VERSION"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("VERSION"), vec![], target.clone()),
&STATS(ref st) =>
Message::format(None, Borrowed("STATS"),
st.as_ref().map(|&(ref query, _)| vec![query.clone()]).unwrap_or(vec![]),
- st.as_ref().and_then(|&(_, ref target)| target.clone()), MsgType::Irc),
+ st.as_ref().and_then(|&(_, ref target)| target.clone())),
&LINKS(ref l) =>
Message::format(None, Borrowed("LINKS"),
l.as_ref().map(|&(ref remote, ref mask)| if remote.is_some() {
vec![remote.clone().unwrap(), mask.clone()] } else { vec![mask.clone()] }).unwrap_or(vec![]),
- None, MsgType::Irc),
+ None),
&TIME(ref target) =>
- Message::format(None, Borrowed("TIME"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("TIME"), vec![], target.clone()),
&CONNECT(ref server, ref port, ref remote) =>
Message::format(None, Borrowed("CONNECT"),
- vec![server.clone(), Owned(format!("{}", port))], remote.clone(), MsgType::Irc),
+ vec![server.clone(), Owned(format!("{}", port))], remote.clone()),
&TRACE(ref target) =>
- Message::format(None, Borrowed("TRACE"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("TRACE"), vec![], target.clone()),
&ADMIN(ref target) =>
- Message::format(None, Borrowed("ADMIN"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("ADMIN"), vec![], target.clone()),
&INFO(ref target) =>
- Message::format(None, Borrowed("INFO"), vec![], target.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("INFO"), vec![], target.clone()),
&SERVLIST(ref sl) =>
Message::format(None, Borrowed("SERVLIST"),
sl.as_ref().map(|&(ref mask, ref target)| target.as_ref()
.map(|t| vec![mask.clone(), t.clone()])
.unwrap_or_else(|| vec![mask.clone()]))
- .unwrap_or(vec![]), None, MsgType::Irc),
+ .unwrap_or(vec![]), None),
&SQUERY(ref name, ref text) =>
Message::format(None, Borrowed("SQUERY"),
- vec![name.clone()], Some(text.clone()), MsgType::Irc),
+ vec![name.clone()], Some(text.clone())),
&WHO(ref mask, o) =>
Message::format(None, Borrowed("WHO"),
match (mask, o) {
(&Some(ref m), true) => vec![m.clone(), Borrowed("o")],
(&Some(ref m), false) => vec![m.clone()],
(&None, _) => vec![]
- }, None, MsgType::Irc),
+ }, None),
&WHOIS(ref target, ref masks) =>
Message::format(None, Borrowed("WHOIS"),
target.as_ref().map(|t| vec![t.clone(), Owned(masks.connect(","))])
- .unwrap_or_else(|| vec![Owned(masks.connect(","))]), None, MsgType::Irc),
+ .unwrap_or_else(|| vec![Owned(masks.connect(","))]), None),
&WHOWAS(ref nick, ref count) =>
Message::format(None, Borrowed("WHOWAS"), match count {
&Some((ref c, Some(ref t))) => vec![Owned(nick.connect(",")), c.clone(), t.clone()],
&Some((ref c, None)) => vec![Owned(nick.connect(",")), c.clone()],
&None => vec![Owned(nick.connect(","))]
- }, None, MsgType::Irc),
+ }, None),
&PING(ref s1, ref s2) =>
- Message::format(None, Borrowed("PING"), vec![s1.clone()], s2.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("PING"), vec![s1.clone()], s2.clone()),
&PONG(ref s1, ref s2) =>
- Message::format(None, Borrowed("PONG"), vec![s1.clone()], s2.clone(), MsgType::Irc),
+ Message::format(None, Borrowed("PONG"), vec![s1.clone()], s2.clone()),
_ => unimplemented!()
}
}
@@ -1947,4 +2038,4 @@ impl<'a> Command<'a> {
}
}
}
-
+*/
diff --git a/src/lib.rs b/src/lib.rs
index d624445..79c2581 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,7 +9,8 @@ extern crate regex;
#[macro_use]
extern crate log;
extern crate openssl;
-extern crate carboxyl;
+extern crate encoding;
+extern crate linear_map;
pub mod client;
pub mod color;
@@ -19,6 +20,7 @@ pub mod message;
pub mod command;
pub mod reply;
pub mod event;
+pub mod text;
use std::io;
use std::result;
@@ -26,12 +28,14 @@ use std::ops::{ Deref, DerefMut };
use openssl::ssl::error::SslError;
+use encoding::EncodingRef;
+
pub use ident::Ident;
-pub use message::{ Message, MsgType };
+pub use message::Message;
pub use command::Command;
pub use reply::Reply;
pub use event::Event;
-pub use client::{ Client, OwnedClient, SharedClient };
+pub use client::Client;
#[derive(Debug)]
pub enum IrscError {
@@ -60,3 +64,4 @@ impl<T> DerefMut for Result<T> {
impl<T> Result<T> { fn inner(self) -> result::Result<T, IrscError> { self.0 } }
pub const DEBUG: bool = cfg!(debug_assertions);
+pub static ENCODING: EncodingRef = encoding::all::UTF_8;
diff --git a/src/message.rs b/src/message.rs
index be52090..de8766c 100644
--- a/src/message.rs
+++ b/src/message.rs
@@ -1,161 +1,191 @@
#![allow(non_camel_case_types)]
-use std::str::FromStr;
+use std::str::{ self, FromStr };
use std::string::{ ToString };
use std::borrow::{ ToOwned };
use std::ops::{ Deref, Range };
+use std::fmt;
+
+use linear_map::LinearMap;
use ::IrscError;
+use text::{ self, Text, TextSlice };
use ident::Ident;
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum MsgType {
- /// Plain old IRC messages, as defined in [rfc2812][rfc]
- /// rfc: http://tools.ietf.org/html/rfc2812
- Irc,
- /// Ctcp messages, wrapped in \u{1}
- Ctcp
-}
-
/// Byte indices, be careful.
-#[derive(Debug, PartialEq, Eq, Clone)]
+/// TODO: more IRCv3 stuff
+/// TODO: have MaybeUTF8 enum, try to decode as UTF-8 first,
+/// with functions to decode as alternative charsets
+/// ircv3.net
+#[derive(Clone)]
pub struct Message {
- pub source: String,
+ pub source: Text,
prefix: Option<Range<u16>>,
command: Range<u16>,
content: Vec<Range<u16>>,
suffix: Option<Range<u16>>,
- pub msg_type: MsgType
+ // only allocates if tags are present
+ tags: LinearMap<Text, Text>
+ //pub msg_type: MsgType
+}
+
+impl fmt::Debug for Message {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_struct("Message")
+ .field("source", &self.source)
+ .finish()
+ }
}
impl Message {
- pub fn new(source: String, prefix: Option<Range<u16>>, command: Range<u16>, content: Vec<Range<u16>>, suffix: Option<Range<u16>>, msg_type: MsgType) -> Message {
+ pub fn new(source: Text, prefix: Option<Range<u16>>, command: Range<u16>, content: Vec<Range<u16>>, suffix: Option<Range<u16>>) -> Message {
Message {
source: source,
prefix: prefix,
command: command,
content: content,
suffix: suffix,
- msg_type: msg_type
+ tags: LinearMap::new()
}
}
- #[allow(unused_assignments)]
- pub fn format<T: Deref<Target=str>>(prefix: Option<T>, command: T, content: Vec<T>, suffix: Option<T>, msg_type: MsgType) -> Message {
- let mut s = String::with_capacity(512);
- let mut i = 0;
-
- let mut i_prefix = None;
- if let Some(ref p) = prefix {
- i_prefix = Some((i + 1) as u16..(i + 2 + p.len()) as u16);
- s.push(':');
- s.push_str(p);
- s.push(' ');
- i += 2 + p.len();
- }
-
- let i_command = i as u16..(i + command.len()) as u16;
- s.push_str(&*command);
- s.push(' ');
- i += 1 + command.len();
-
- let mut i_content = Vec::new();
- for part in content.iter() {
- i_content.push(i as u16..(i + part.len()) as u16);
- s.push_str(part);
- s.push(' ');
- i += 1 + part.len();
- }
-
- let mut i_suffix = None;
- if let Some(ref p) = suffix {
- s.push(':');
- if let MsgType::Ctcp = msg_type { s.push('\u{1}'); i += 1; }
- let n = i;
- s.push_str(p);
- if let MsgType::Ctcp = msg_type { s.push('\u{1}'); i += 1; }
- i_suffix = Some(n as u16..(n + p.len()) as u16);
- i += 1 + p.len();
- }
-
- s.push_str("\r\n");
- i += 2;
-
- Message::new(s, i_prefix, i_command, i_content, i_suffix, msg_type)
- }
-
- pub fn range(&self, r: &Range<u16>) -> &str {
- &self.source[r.start as usize..r.end as usize]
- }
-
- pub fn prefix(&self) -> Option<&str> { self.prefix.as_ref().map(|r| self.range(r)) }
- pub fn command(&self) -> &str { self.range(&self.command) }
- pub fn content(&self) -> Vec<&str> { self.content.iter().map(|r| self.range(&r)).collect() }
- pub fn suffix(&self) -> Option<&str> { self.suffix.as_ref().map(|r| self.range(r)) }
- pub fn elements(&self) -> Vec<&str> { let mut s = self.content(); self.suffix().map(|f| s.push(f)); s }
- pub fn ident(&self) -> Option<Ident> { self.prefix().and_then(Ident::parse) }
-}
-
-impl FromStr for Message {
- type Err = IrscError;
- fn from_str(i: &str) -> Result<Message, IrscError> {
+ fn parse(i: &[u8]) -> Result<Message, IrscError> {
let len = i.len();
+ // Use indices instead of subslices, to store
// remember, bytes, not chars
let mut s = 0;
- let prefix = if len >= 1 && i[s..].as_bytes()[0] == ':' as u8 {
- i[s..].find(' ').map(|i| { let n = 1u16..(s + i) as u16; s += i + 1; n })
+ let prefix = if len >= 1 && i[s] == b':' {
+ i[s..].iter().cloned()
+ .find(|&b| b == b' ')
+ .map(|j| { let n = 1u16..(s + j as usize) as u16; s += j as usize + 1; n })
} else { None };
- let command = i[s..].find(' ').map(|n| {
- let p = s as u16..(s + n) as u16;
- s += n;
+ let command = i[s..].iter().cloned()
+ .find(|&b| b == b' ').map(|n| {
+ let p = s as u16..(s + n as usize) as u16;
+ s += n as usize;
p
});
- let mut content = Vec::with_capacity(15);
+ let mut content = Vec::with_capacity(3);
let mut suffix = None;
while s < len - 3 {
- if i[s..].as_bytes()[0] == ':' as u8 {
+ if i[s] == b':' {
suffix = Some(s as u16 + 1 as u16..i.len() as u16);
break
}
- i[s..].find(' ').map(|i| {
- if i > 0 {
- content.push(s as u16..(s + i) as u16);
- s += i;
+ i[s..].iter().cloned()
+ .find(|&b| b == b' ').map(|j| {
+ if j > 0 {
+ content.push(s as u16..(s + j as usize) as u16);
+ s += j as usize;
}
});
// if s.chars().next() == Some(' ') { s = &s[1..] };
s += 1;
}
- let msg_type = if suffix.as_ref().map(|s| i[s.start as usize..].as_bytes()[0] == 1
+ /*let msg_type = if suffix.as_ref().map(|s| i[s.start as usize..].as_bytes()[0] == 1
&& i[(s.end - 3) as usize..].as_bytes()[0] == 1)
- == Some(true) { MsgType::Ctcp } else { MsgType::Irc };
+ == Some(true) { MsgType::Ctcp } else { MsgType::Irc };*/
command.map(move |c|
Ok(Message::new(
- i.to_owned(),
+ Text::Raw(i.to_owned()),
prefix,
c,
content,
// strip \{1} if CTCP message
// strip \r\n for each line, relying on their existence
- match msg_type {
+ suffix
+ /*match msg_type {
MsgType::Irc => suffix.map(|s| s.start..s.end - 1),
MsgType::Ctcp => suffix.map(|s| s.start + 1..s.end - 2)
},
- msg_type
+ msg_type*/
))
).unwrap()
+ }
+
+ #[allow(unused_assignments)]
+ pub fn format<T: Deref<Target=[u8]>>(prefix: Option<T>, command: T, content: Vec<T>, suffix: Option<T>) -> Message {
+ let mut s = Vec::with_capacity(512);
+ let mut i = 0;
+
+ let mut i_prefix = None;
+ if let Some(ref p) = prefix {
+ i_prefix = Some((i + 1) as u16..(i + 2 + p.len()) as u16);
+ s.push(b':');
+ s.push_all(p);
+ s.push(b' ');
+ i = s.len();
+ }
+
+ let i_command = i as u16..(i + command.len()) as u16;
+ s.push_all(&command);
+ s.push(b' ');
+ i = s.len();
+
+ let mut i_content = Vec::new();
+ for part in content.iter() {
+ i_content.push(i as u16..(i + part.len()) as u16);
+ s.push_all(part);
+ s.push(b' ');
+ i = s.len();
+ }
+
+ let mut i_suffix = None;
+ if let Some(ref p) = suffix {
+ s.push(b':');
+ //if let MsgType::Ctcp = msg_type { s.push('\u{1}'); i += 1; }
+ let n = i;
+ s.push_all(p);
+ //if let MsgType::Ctcp = msg_type { s.push('\u{1}'); i += 1; }
+ i_suffix = Some(n as u16..(n + p.len()) as u16);
+ i = s.len();
+ }
+ s.push_all(b"\r\n");
+
+ Message::new(Text::Raw(s), i_prefix, i_command, i_content, i_suffix)
}
-}
-impl ToString for Message {
- fn to_string(&self) -> String {
- self.source.clone()
+ pub fn byte_range(&self, r: &Range<u16>) -> &[u8] {
+ &self.source[r.start as usize..r.end as usize]
+ }
+
+ pub fn text_range(&self, r: &Range<u16>) -> TextSlice {
+ self.source.slice(&(r.start as usize..r.end as usize))
+ }
+
+ pub fn string_range(&self, r: &Range<u16>) -> String {
+ text::def_lossy_decode(self.byte_range(r))
+ }
+
+ pub fn str_range(&self, r: &Range<u16>) -> Option<&str> {
+ str::from_utf8(self.byte_range(r)).ok()
+ }
+
+ pub fn bytes(&self) -> &[u8] { &*self.source }
+
+ pub fn prefix<'a>(&'a self) -> Option<TextSlice<'a>> {
+ self.prefix.as_ref().map(|r| self.text_range(r)) }
+ pub fn command<'a>(&'a self) -> TextSlice<'a> {
+ self.text_range(&self.command) }
+ pub fn content<'a>(&'a self) -> Vec<TextSlice<'a>> {
+ self.content.iter().map(|r| self.text_range(&r)).collect() }
+ pub fn suffix<'a>(&'a self) -> Option<TextSlice<'a>> {
+ self.suffix.as_ref().map(|r| self.text_range(r)) }
+ pub fn last<'a>(&'a self) -> Option<TextSlice<'a>> {
+ self.suffix().or(self.content.last().map(|l| self.text_range(l))) }
+ pub fn elements<'a>(&'a self) -> Vec<TextSlice<'a>> {
+ let mut s = self.content(); self.suffix().map(|f| s.push(f)); s }
+ pub fn ident(&self) -> Option<Ident> {
+ self.prefix().and_then(|p| p.utf8()).and_then(Ident::parse) }
+ pub fn is_ctcp(&self) -> bool {
+ self.source.get(0) == Some(&1)
+ && self.source.get(self.source.length() - 3) == Some(&1)
}
}
diff --git a/src/reply.rs b/src/reply.rs
index 7b594ff..a1f1dad 100644
--- a/src/reply.rs
+++ b/src/reply.rs
@@ -3,34 +3,100 @@ use std::borrow::{ Cow, ToOwned };
use std::borrow::Cow::*;
use ::{ Result, IrscError };
-use ::message::{ MsgType, Message };
-
-pub type CS<'a> = Cow<'a, str>;
-
-#[allow(non_camel_case_types)]
-#[derive(Debug, Hash, Clone, PartialEq, Eq)]
-pub enum Reply<'a> {
- /// 001 RPL_WELCOME
- /// "Welcome to the Internet Relay Network
- /// <nick>!<user>@<host>"
- RPL_WELCOME(CS<'a>),
+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),*)
+ ),+
+ }
- /// 002 RPL_YOURHOST
- /// "Your host is <servername>, running version <ver>"
- RPL_YOURHOST(CS<'a>),
+ #[allow(non_camel_case_types)]
+ #[derive(Debug, Hash, Clone, PartialEq, Eq)]
+ pub enum OwnedReply {
+ $(
+ #[$doc]
+ $name($($owned_items),*)
+ ),+
+ }
- /// 003 RPL_CREATED
- /// "This server was created <date>"
- RPL_CREATED(CS<'a>),
+ 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<Reply<'a>> {
+ 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)
+ ),+
+ }
+ }
+ }
+ )
+}
- /// 004 RPL_MYINFO
- /// "<servername> <version> <available user modes>
- /// <available channel modes>"
- ///
- /// - The server sends Replies 001 to 004 to a user upon
- /// successful registration.
- ///
- RPL_MYINFO(CS<'a>),
+replies! {
+ RPL_WELCOME {
+ "001", doc = r#"001 RPL_WELCOME
+ "Welcome to the Internet Relay Network
+ <nick>!<user>@<host>""#
+ b &'a [u8]
+ o Vec<u8>
+ t s => s.into()
+ },
+ RPL_YOURHOST {
+ "002", doc = r#"002 RPL_YOURHOST
+ "Your host is <servername>, running version <ver>""#
+ b &'a [u8]
+ o Vec<u8>
+ t s => s.into()
+ },
+ RPL_CREATED {
+ "003", doc = r#"003 RPL_CREATED
+ "This server was created <date>""#
+ b &'a [u8]
+ o Vec<u8>
+ t s => s.into()
+ },
+ RPL_MYINFO {
+ "004", doc = r#"004 RPL_MYINFO
+ "<servername> <version> <available user modes>
+ <available channel modes>"
+
+ - The server sends Replies 001 to 004 to a user upon
+ successful registration."#
+ b &'a [u8], &'a [u8], &'a [u8]
+ o Vec<u8>
+ t s => s.into()
+ }
+}
+ /*
+ RPL_MYINFO(&'a [u8]),
/// 005 RPL_BOUNCE
/// "Try server <server name>, port <port number>"
@@ -39,7 +105,7 @@ pub enum Reply<'a> {
/// server. This is often used when the connection is
/// refused because the server is already full.
///
- RPL_BOUNCE(CS<'a>),
+ RPL_BOUNCE(&'a [u8]),
/// 302 RPL_USERHOST
/// ":*1<reply> *( " " <reply> )"
@@ -55,7 +121,7 @@ pub enum Reply<'a> {
/// whether the client has set an AWAY message or not
/// respectively.
///
- RPL_USERHOST(CS<'a>),
+ RPL_USERHOST(&'a [u8]),
/// 303 RPL_ISON
/// ":*1<nick> *( " " <nick> )"
@@ -63,15 +129,15 @@ pub enum Reply<'a> {
/// - Reply format used by ISON to list replies to the
/// query list.
///
- RPL_ISON(CS<'a>),
+ RPL_ISON(&'a [u8]),
/// 301 RPL_AWAY
/// "<nick> :<away message>"
- RPL_AWAY(CS<'a>),
+ RPL_AWAY(&'a [u8]),
/// 305 RPL_UNAWAY
/// ":You are no longer marked as being away"
- RPL_UNAWAY(CS<'a>),
+ RPL_UNAWAY(&'a [u8]),
/// 306 RPL_NOWAWAY
/// ":You have been marked as being away"
@@ -83,27 +149,27 @@ pub enum Reply<'a> {
/// Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
/// client removes and sets an AWAY message.
///
- RPL_NOWAWAY(CS<'a>),
+ RPL_NOWAWAY(&'a [u8]),
/// 311 RPL_WHOISUSER
/// "<nick> <user> <host> * :<real name>"
- RPL_WHOISUSER(CS<'a>),
+ RPL_WHOISUSER(&'a [u8]),
/// 312 RPL_WHOISSERVER
/// "<nick> <server> :<server info>"
- RPL_WHOISSERVER(CS<'a>),
+ RPL_WHOISSERVER(&'a [u8]),
/// 313 RPL_WHOISOPERATOR
/// "<nick> :is an IRC operator"
- RPL_WHOISOPERATOR(CS<'a>),
+ RPL_WHOISOPERATOR(&'a [u8]),
/// 317 RPL_WHOISIDLE
/// "<nick> <integer> :seconds idle"
- RPL_WHOISIDLE(CS<'a>),
+ RPL_WHOISIDLE(&'a [u8]),
/// 318 RPL_ENDOFWHOIS
/// "<nick> :End of WHOIS list"
- RPL_ENDOFWHOIS(CS<'a>),
+ RPL_ENDOFWHOIS(&'a [u8]),
/// 319 RPL_WHOISCHANNELS
/// "<nick> :*( ( "@" / "+" ) <channel> " " )"
@@ -123,11 +189,11 @@ pub enum Reply<'a> {
/// channel. The RPL_ENDOFWHOIS reply is used to mark
/// the end of processing a WHOIS message.
///
- RPL_WHOISCHANNELS(CS<'a>),
+ RPL_WHOISCHANNELS(&'a [u8]),
/// 314 RPL_WHOWASUSER
/// "<nick> <user> <host> * :<real name>"
- RPL_WHOWASUSER(CS<'a>),
+ RPL_WHOWASUSER(&'a [u8]),
/// 369 RPL_ENDOFWHOWAS
/// "<nick> :End of WHOWAS"
@@ -139,7 +205,7 @@ pub enum Reply<'a> {
/// be RPL_ENDOFWHOWAS (even if there was only one reply
/// and it was an error).
///
- RPL_ENDOFWHOWAS(CS<'a>),
+ RPL_ENDOFWHOWAS(&'a [u8]),
/// 321 RPL_LISTSTART
/// Obsolete. Not used.
@@ -148,7 +214,7 @@ pub enum Reply<'a> {
/// 322 RPL_LIST
/// "<channel> <# visible> :<topic>"
- RPL_LIST(CS<'a>),
+ RPL_LIST(&'a [u8]),
/// 323 RPL_LISTEND
/// ":End of LIST"
@@ -158,21 +224,21 @@ pub enum Reply<'a> {
/// command. If there are no channels available to return,
/// only the end reply MUST be sent.
///
- RPL_LISTEND(CS<'a>),
+ RPL_LISTEND(&'a [u8]),
/// 325 RPL_UNIQOPIS
/// "<channel> <nickname>"
///
- RPL_UNIQOPIS(CS<'a>),
+ RPL_UNIQOPIS(&'a [u8]),
/// 324 RPL_CHANNELMODEIS
/// "<channel> <mode> <mode params>"
///
- RPL_CHANNELMODEIS(CS<'a>),
+ RPL_CHANNELMODEIS(&'a [u8]),
/// 331 RPL_NOTOPIC
/// "<channel> :No topic is set"
- RPL_NOTOPIC(CS<'a>),
+ RPL_NOTOPIC(&'a [u8]),
/// 332 RPL_TOPIC
/// "<channel> :<topic>"
@@ -182,7 +248,7 @@ pub enum Reply<'a> {
/// the topic is set, RPL_TOPIC is sent back else
/// RPL_NOTOPIC.
///
- RPL_TOPIC(CS<'a>),
+ RPL_TOPIC(&'a [u8]),
/// 341 RPL_INVITING
/// "<channel> <nick>"
@@ -191,7 +257,7 @@ pub enum Reply<'a> {
/// attempted INVITE message was successful and is
/// being passed onto the end client.
///
- RPL_INVITING(CS<'a>),
+ RPL_INVITING(&'a [u8]),
/// 342 RPL_SUMMONING
/// "<user> :Summoning user to IRC"
@@ -199,11 +265,11 @@ pub enum Reply<'a> {
/// - Returned by a server answering a SUMMON message to
/// indicate that it is summoning that user.
///
- RPL_SUMMONING(CS<'a>),
+ RPL_SUMMONING(&'a [u8]),
/// 346 RPL_INVITELIST
/// "<channel> <invitemask>"
- RPL_INVITELIST(CS<'a>),
+ RPL_INVITELIST(&'a [u8]),
/// 347 RPL_ENDOFINVITELIST
/// "<channel> :End of channel invite list"
@@ -215,11 +281,11 @@ pub enum Reply<'a> {
/// After the masks have been listed (or if none present) a
/// RPL_ENDOFINVITELIST MUST be sent.
///
- RPL_ENDOFINVITELIST(CS<'a>),
+ RPL_ENDOFINVITELIST(&'a [u8]),
/// 348 RPL_EXCEPTLIST
/// "<channel> <exceptionmask>"
- RPL_EXCEPTLIST(CS<'a>),
+ RPL_EXCEPTLIST(&'a [u8]),
/// 349 RPL_ENDOFEXCEPTLIST
/// "<channel> :End of channel exception list"
@@ -231,7 +297,7 @@ pub enum Reply<'a> {
/// After the masks have been listed (or if none present)
/// a RPL_ENDOFEXCEPTLIST MUST be sent.
///
- RPL_ENDOFEXCEPTLIST(CS<'a>),
+ RPL_ENDOFEXCEPTLIST(&'a [u8]),
/// 351 RPL_VERSION
/// "<version>.<debuglevel> <server> :<comments>"
@@ -245,14 +311,14 @@ pub enum Reply<'a> {
/// The "comments" field may contain any comments about
/// the version or further version details.
///
- RPL_VERSION(CS<'a>),
+ RPL_VERSION(&'a [u8]),
/// 352 RPL_WHOREPLY
/// "<channel> <user> <host> <server> <nick>
/// ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
/// :<hopcount> <real name>"
///
- RPL_WHOREPLY(CS<'a>),
+ RPL_WHOREPLY(&'a [u8]),
/// 315 RPL_ENDOFWHO
/// "<name> :End of WHO list"
@@ -265,7 +331,7 @@ pub enum Reply<'a> {
/// after processing each list item with <name> being
/// the item.
///
- RPL_ENDOFWHO(CS<'a>),
+ RPL_ENDOFWHO(&'a [u8]),
/// 353 RPL_NAMREPLY
/// "( "=" / "*" / "@" ) <channel>
@@ -273,7 +339,7 @@ pub enum Reply<'a> {
/// - "@" is used for secret channels, "*" for private
/// channels, and "=" for others (public channels).
///
- RPL_NAMREPLY(CS<'a>),
+ RPL_NAMREPLY(&'a [u8]),
/// 366 RPL_ENDOFNAMES
/// "<channel> :End of NAMES list"
@@ -288,11 +354,11 @@ pub enum Reply<'a> {
/// RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
/// the end.
///
- RPL_ENDOFNAMES(CS<'a>),
+ RPL_ENDOFNAMES(&'a [u8]),
/// 364 RPL_LINKS
/// "<mask> <server> :<hopcount> <server info>"
- RPL_LINKS(CS<'a>),
+ RPL_LINKS(&'a [u8]),
/// 365 RPL_ENDOFLINKS
/// "<mask> :End of LINKS list"
@@ -301,11 +367,11 @@ pub enum Reply<'a> {
/// replies back using the RPL_LINKS numeric and mark the
/// end of the list using an RPL_ENDOFLINKS reply.
///
- RPL_ENDOFLINKS(CS<'a>),
+ RPL_ENDOFLINKS(&'a [u8]),
/// 367 RPL_BANLIST
/// "<channel> <banmask>"
- RPL_BANLIST(CS<'a>),
+ RPL_BANLIST(&'a [u8]),
/// 368 RPL_ENDOFBANLIST
/// "<channel> :End of channel ban list"
@@ -317,11 +383,11 @@ pub enum Reply<'a> {
/// banmasks have been listed (or if none present) a
/// RPL_ENDOFBANLIST MUST be sent.
///
- RPL_ENDOFBANLIST(CS<'a>),
+ RPL_ENDOFBANLIST(&'a [u8]),
/// 371 RPL_INFO
/// ":<string>"
- RPL_INFO(CS<'a>),
+ RPL_INFO(&'a [u8]),
/// 374 RPL_ENDOFINFO
/// ":End of INFO list"
@@ -331,15 +397,15 @@ pub enum Reply<'a> {
/// with a RPL_ENDOFINFO reply to indicate the end of the
/// replies.
///
- RPL_ENDOFINFO(CS<'a>),
+ RPL_ENDOFINFO(&'a [u8]),
/// 375 RPL_MOTDSTART
/// ":- <server> Message of the day - "
- RPL_MOTDSTART(CS<'a>),
+ RPL_MOTDSTART(&'a [u8]),
/// 372 RPL_MOTD
/// ":- <text>"
- RPL_MOTD(CS<'a>),
+ RPL_MOTD(&'a [u8]),
/// 376 RPL_ENDOFMOTD
/// ":End of MOTD command"
@@ -351,7 +417,7 @@ pub enum Reply<'a> {
/// by a RPL_MOTDSTART (before the RPL_MOTDs) and an
/// RPL_ENDOFMOTD (after).
///
- RPL_ENDOFMOTD(CS<'a>),
+ RPL_ENDOFMOTD(&'a [u8]),
/// 381 RPL_YOUREOPER
/// ":You are now an IRC operator"
@@ -360,7 +426,7 @@ pub enum Reply<'a> {
/// just successfully issued an OPER message and gained
/// operator status.
///
- RPL_YOUREOPER(CS<'a>),
+ RPL_YOUREOPER(&'a [u8]),
/// 382 RPL_REHASHING
/// "<config file> :Rehashing"
@@ -369,7 +435,7 @@ pub enum Reply<'a> {
/// a REHASH message, an RPL_REHASHING is sent back to
/// the operator.
///
- RPL_REHASHING(CS<'a>),
+ RPL_REHASHING(&'a [u8]),
/// 383 RPL_YOURESERVICE
/// "You are service <servicename>"
@@ -377,7 +443,7 @@ pub enum Reply<'a> {
/// - Sent by the server to a service upon successful
/// registration.
///
- RPL_YOURESERVICE(CS<'a>),
+ RPL_YOURESERVICE(&'a [u8]),
/// 391 RPL_TIME
/// "<server> :<string showing server's local time>"
@@ -388,19 +454,19 @@ pub enum Reply<'a> {
/// time there. There is no further requirement for the
/// time string.
///
- RPL_TIME(CS<'a>),
+ RPL_TIME(&'a [u8]),
/// 392 RPL_USERSSTART
/// ":UserID Terminal Host"
- RPL_USERSSTART(CS<'a>),
+ RPL_USERSSTART(&'a [u8]),
/// 393 RPL_USERS
/// ":<username> <ttyline> <hostname>"
- RPL_USERS(CS<'a>),
+ RPL_USERS(&'a [u8]),
/// 394 RPL_ENDOFUSERS
/// ":End of users"
- RPL_ENDOFUSERS(CS<'a>),
+ RPL_ENDOFUSERS(&'a [u8]),
/// 395 RPL_NOUSERS
/// ":Nobody logged in"
@@ -412,59 +478,59 @@ pub enum Reply<'a> {
/// or a single RPL_NOUSER. Following this is
/// RPL_ENDOFUSERS.
///
- RPL_NOUSERS(CS<'a>),
+ RPL_NOUSERS(&'a [u8]),
/// 200 RPL_TRACELINK
/// "Link <version & debug level> <destination>
/// <next server> V<protocol version>
/// <link uptime in seconds> <backstream sendq>
/// <upstream sendq>"
- RPL_TRACELINK(CS<'a>),
+ RPL_TRACELINK(&'a [u8]),
/// 201 RPL_TRACECONNECTING
/// "Try. <class> <server>"
- RPL_TRACECONNECTING(CS<'a>),
+ RPL_TRACECONNECTING(&'a [u8]),
/// 202 RPL_TRACEHANDSHAKE
/// "H.S. <class> <server>"
- RPL_TRACEHANDSHAKE(CS<'a>),
+ RPL_TRACEHANDSHAKE(&'a [u8]),
/// 203 RPL_TRACEUNKNOWN
/// "???? <class> [<client IP address in dot form>]"
- RPL_TRACEUNKNOWN(CS<'a>),
+ RPL_TRACEUNKNOWN(&'a [u8]),
/// 204 RPL_TRACEOPERATOR
/// "Oper <class> <nick>"
- RPL_TRACEOPERATOR(CS<'a>),
+ RPL_TRACEOPERATOR(&'a [u8]),
/// 205 RPL_TRACEUSER
/// "User <class> <nick>"
- RPL_TRACEUSER(CS<'a>),
+ RPL_TRACEUSER(&'a [u8]),
/// 206 RPL_TRACESERVER
/// "Serv <class> <int>S <int>C <server>
/// <nick!user|*!*>@<host|server> V<protocol version>"
- RPL_TRACESERVER(CS<'a>),
+ RPL_TRACESERVER(&'a [u8]),
/// 207 RPL_TRACESERVICE
/// "Service <class> <name> <type> <active type>"
- RPL_TRACESERVICE(CS<'a>),
+ RPL_TRACESERVICE(&'a [u8]),
/// 208 RPL_TRACENEWTYPE
/// "<newtype> 0 <client name>"
- RPL_TRACENEWTYPE(CS<'a>),
+ RPL_TRACENEWTYPE(&'a [u8]),
/// 209 RPL_TRACECLASS
/// "Class <class> <count>"
- RPL_TRACECLASS(CS<'a>),
+ RPL_TRACECLASS(&'a [u8]),
/// 210 RPL_TRACERECONNECT
/// Unused.
- RPL_TRACERECONNECT(CS<'a>),
+ RPL_TRACERECONNECT(&'a [u8]),
/// 261 RPL_TRACELOG
/// "File <logfile> <debug level>"
- RPL_TRACELOG(CS<'a>),
+ RPL_TRACELOG(&'a [u8]),
/// 262 RPL_TRACEEND
/// "<server name> <version & debug level> :End of TRACE"
@@ -491,7 +557,7 @@ pub enum Reply<'a> {
/// being displayed anyway.
/// RPL_TRACEEND is sent to indicate the end of the list.
///
- RPL_TRACEEND(CS<'a>),
+ RPL_TRACEEND(&'a [u8]),
/// 211 RPL_STATSLINKINFO
/// "<linkname> <sendq> <sent messages>
@@ -509,26 +575,26 @@ pub enum Reply<'a> {
/// open> indicates how long ago the connection was
/// opened, in seconds.
///
- RPL_STATSLINKINFO(CS<'a>),
+ RPL_STATSLINKINFO(&'a [u8]),
/// 212 RPL_STATSCOMMANDS
/// "<command> <count> <byte count> <remote count>"
///
/// - reports statistics on commands usage.
///
- RPL_STATSCOMMANDS(CS<'a>),
+ RPL_STATSCOMMANDS(&'a [u8]),
/// 219 RPL_ENDOFSTATS
/// "<stats letter> :End of STATS report"
///
- RPL_ENDOFSTATS(CS<'a>),
+ RPL_ENDOFSTATS(&'a [u8]),
/// 242 RPL_STATSUPTIME
/// ":Server Up %d days %d:%02d:%02d"
///
/// - reports the server uptime.
///
- RPL_STATSUPTIME(CS<'a>),
+ RPL_STATSUPTIME(&'a [u8]),
/// 243 RPL_STATSOLINE
/// "O <hostmask> * <name>"
@@ -536,7 +602,7 @@ pub enum Reply<'a> {
/// - reports the allowed hosts from where user may become IRC
/// operators.
///
- RPL_STATSOLINE(CS<'a>),
+ RPL_STATSOLINE(&'a [u8]),
/// 221 RPL_UMODEIS
/// "<user mode string>"
@@ -544,12 +610,12 @@ pub enum Reply<'a> {
/// - To answer a query about a client's own mode,
/// RPL_UMODEIS is sent back.
///
- RPL_UMODEIS(CS<'a>),
+ RPL_UMODEIS(&'a [u8]),
/// 234 RPL_SERVLIST
/// "<name> <server> <mask> <type> <hopcount> <info>"
///
- RPL_SERVLIST(CS<'a>),
+ RPL_SERVLIST(&'a [u8]),
/// 235 RPL_SERVLISTEND
/// "<mask> <type> :End of service listing"
@@ -561,24 +627,24 @@ pub enum Reply<'a> {
/// services have been listed (or if none present) a
/// RPL_SERVLISTEND MUST be sent.
///
- RPL_SERVLISTEND(CS<'a>),
+ RPL_SERVLISTEND(&'a [u8]),
/// 251 RPL_LUSERCLIENT
/// ":There are <integer> users and <integer>
/// services on <integer> servers"
- RPL_LUSERCLIENT(CS<'a>),
+ RPL_LUSERCLIENT(&'a [u8]),
/// 252 RPL_LUSEROP
/// "<integer> :operator(s) online"
- RPL_LUSEROP(CS<'a>),
+ RPL_LUSEROP(&'a [u8]),
/// 253 RPL_LUSERUNKNOWN
/// "<integer> :unknown connection(s)"
- RPL_LUSERUNKNOWN(CS<'a>),
+ RPL_LUSERUNKNOWN(&'a [u8]),
/// 254 RPL_LUSERCHANNELS
/// "<integer> :channels formed"
- RPL_LUSERCHANNELS(CS<'a>),
+ RPL_LUSERCHANNELS(&'a [u8]),
/// 255 RPL_LUSERME
/// ":I have <integer> clients and <integer>
@@ -593,19 +659,19 @@ pub enum Reply<'a> {
/// replies are only sent back if a non-zero count
/// is found for them.
///
- RPL_LUSERME(CS<'a>),
+ RPL_LUSERME(&'a [u8]),
/// 256 RPL_ADMINME
/// "<server> :Administrative info"
- RPL_ADMINME(CS<'a>),
+ RPL_ADMINME(&'a [u8]),
/// 257 RPL_ADMINLOC1
/// ":<admin info>"
- RPL_ADMINLOC1(CS<'a>),
+ RPL_ADMINLOC1(&'a [u8]),
/// 258 RPL_ADMINLOC2
/// ":<admin info>"
- RPL_ADMINLOC2(CS<'a>),
+ RPL_ADMINLOC2(&'a [u8]),
/// 259 RPL_ADMINEMAIL
/// ":<admin info>"
@@ -622,7 +688,7 @@ pub enum Reply<'a> {
/// server (an email address here is REQUIRED)
/// in RPL_ADMINEMAIL.
///
- RPL_ADMINEMAIL(CS<'a>),
+ RPL_ADMINEMAIL(&'a [u8]),
/// 263 RPL_TRYAGAIN
/// "<command> :Please wait a while and try again."
@@ -631,7 +697,7 @@ pub enum Reply<'a> {
/// it MUST use the reply RPL_TRYAGAIN to inform the
/// originating client.
///
- RPL_TRYAGAIN(CS<'a>),
+ RPL_TRYAGAIN(&'a [u8]),
/// 401 ERR_NOSUCHNICK
/// "<nickname> :No such nick/channel"
@@ -639,7 +705,7 @@ pub enum Reply<'a> {
/// - Used to indicate the nickname parameter supplied to a
/// command is currently unused.
///
- ERR_NOSUCHNICK(CS<'a>),
+ ERR_NOSUCHNICK(&'a [u8]),
/// 402 ERR_NOSUCHSERVER
/// "<server name> :No such server"
@@ -647,14 +713,14 @@ pub enum Reply<'a> {
/// - Used to indicate the server name given currently
/// does not exist.
///
- ERR_NOSUCHSERVER(CS<'a>),
+ ERR_NOSUCHSERVER(&'a [u8]),
/// 403 ERR_NOSUCHCHANNEL
/// "<channel name> :No such channel"
///
/// - Used to indicate the given channel name is invalid.
///
- ERR_NOSUCHCHANNEL(CS<'a>),
+ ERR_NOSUCHCHANNEL(&'a [u8]),
/// 404 ERR_CANNOTSENDTOCHAN
/// "<channel name> :Cannot send to channel"
@@ -665,7 +731,7 @@ pub enum Reply<'a> {
/// banned and is trying to send a PRIVMSG message to
/// that channel.
///
- ERR_CANNOTSENDTOCHAN(CS<'a>),
+ ERR_CANNOTSENDTOCHAN(&'a [u8]),
/// 405 ERR_TOOMANYCHANNELS
/// "<channel name> :You have joined too many channels"
@@ -674,7 +740,7 @@ pub enum Reply<'a> {
/// number of allowed channels and they try to join
/// another channel.
///
- ERR_TOOMANYCHANNELS(CS<'a>),
+ ERR_TOOMANYCHANNELS(&'a [u8]),
/// 406 ERR_WASNOSUCHNICK
/// "<nickname> :There was no such nickname"
@@ -682,7 +748,7 @@ pub enum Reply<'a> {
/// - Returned by WHOWAS to indicate there is no history
/// information for that nickname.
///
- ERR_WASNOSUCHNICK(CS<'a>),
+ ERR_WASNOSUCHNICK(&'a [u8]),
/// 407 ERR_TOOMANYTARGETS
/// "<target> :<error code> recipients. <abort message>"
@@ -698,7 +764,7 @@ pub enum Reply<'a> {
/// channel using the shortname when there are more than one
/// such channel.
///
- ERR_TOOMANYTARGETS(CS<'a>),
+ ERR_TOOMANYTARGETS(&'a [u8]),
/// 408 ERR_NOSUCHSERVICE
/// "<service name> :No such service"
@@ -706,30 +772,30 @@ pub enum Reply<'a> {
/// - Returned to a client which is attempting to send a SQUERY
/// to a service which does not exist.
///
- ERR_NOSUCHSERVICE(CS<'a>),
+ ERR_NOSUCHSERVICE(&'a [u8]),
/// 409 ERR_NOORIGIN
/// ":No origin specified"
///
/// - PING or PONG message missing the originator parameter.
///
- ERR_NOORIGIN(CS<'a>),
+ ERR_NOORIGIN(&'a [u8]),
/// 411 ERR_NORECIPIENT
/// ":No recipient given (<command>)"
- ERR_NORECIPIENT(CS<'a>),
+ ERR_NORECIPIENT(&'a [u8]),
/// 412 ERR_NOTEXTTOSEND
/// ":No text to send"
- ERR_NOTEXTTOSEND(CS<'a>),
+ ERR_NOTEXTTOSEND(&'a [u8]),
/// 413 ERR_NOTOPLEVEL
/// "<mask> :No toplevel domain specified"
- ERR_NOTOPLEVEL(CS<'a>),
+ ERR_NOTOPLEVEL(&'a [u8]),
/// 414 ERR_WILDTOPLEVEL
/// "<mask> :Wildcard in toplevel domain"
- ERR_WILDTOPLEVEL(CS<'a>),
+ ERR_WILDTOPLEVEL(&'a [u8]),
/// 415 ERR_BADMASK
/// "<mask> :Bad Server/host mask"
@@ -740,7 +806,7 @@ pub enum Reply<'a> {
/// are returned when an invalid use of
/// "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
///
- ERR_BADMASK(CS<'a>),
+ ERR_BADMASK(&'a [u8]),
/// 421 ERR_UNKNOWNCOMMAND
/// "<command> :Unknown command"
@@ -748,14 +814,14 @@ pub enum Reply<'a> {
/// - Returned to a registered client to indicate that the
/// command sent is unknown by the server.
///
- ERR_UNKNOWNCOMMAND(CS<'a>),
+ ERR_UNKNOWNCOMMAND(&'a [u8]),
/// 422 ERR_NOMOTD
/// ":MOTD File is missing"
///
/// - Server's MOTD file could not be opened by the server.
///
- ERR_NOMOTD(CS<'a>),
+ ERR_NOMOTD(&'a [u8]),
/// 423 ERR_NOADMININFO
/// "<server> :No administrative info available"
@@ -764,7 +830,7 @@ pub enum Reply<'a> {
/// when there is an error in finding the appropriate
/// information.
///
- ERR_NOADMININFO(CS<'a>),
+ ERR_NOADMININFO(&'a [u8]),
/// 424 ERR_FILEERROR
/// ":File error doing <file op> on <file>"
@@ -772,7 +838,7 @@ pub enum Reply<'a> {
/// - Generic error message used to report a failed file
/// operation during the processing of a message.
///
- ERR_FILEERROR(CS<'a>),
+ ERR_FILEERROR(&'a [u8]),
/// 431 ERR_NONICKNAMEGIVEN
/// ":No nickname given"
@@ -780,7 +846,7 @@ pub enum Reply<'a> {
/// - Returned when a nickname parameter expected for a
/// command and isn't found.
///
- ERR_NONICKNAMEGIVEN(CS<'a>),
+ ERR_NONICKNAMEGIVEN(&'a [u8]),
/// 432 ERR_ERRONEUSNICKNAME
/// "<nick> :Erroneous nickname"
@@ -789,7 +855,7 @@ pub enum Reply<'a> {
/// characters which do not fall in the defined set. See
/// section 2.3.1 for details on valid nicknames.
///
- ERR_ERRONEUSNICKNAME(CS<'a>),
+ ERR_ERRONEUSNICKNAME(&'a [u8]),
/// 433 ERR_NICKNAMEINUSE
/// "<nick> :Nickname is already in use"
@@ -798,7 +864,7 @@ pub enum Reply<'a> {
/// in an attempt to change to a currently existing
/// nickname.
///
- ERR_NICKNAMEINUSE(CS<'a>),
+ ERR_NICKNAMEINUSE(&'a [u8]),
/// 436 ERR_NICKCOLLISION
/// "<nick> :Nickname collision KILL from <user>@<host>"
@@ -807,7 +873,7 @@ pub enum Reply<'a> {
/// nickname collision (registered of a NICK that
/// already exists by another server).
///
- ERR_NICKCOLLISION(CS<'a>),
+ ERR_NICKCOLLISION(&'a [u8]),
/// 437 ERR_UNAVAILRESOURCE
/// "<nick/channel> :Nick/channel is temporarily unavailable"
@@ -819,7 +885,7 @@ pub enum Reply<'a> {
/// when the desired nickname is blocked by the nick delay
/// mechanism.
///
- ERR_UNAVAILRESOURCE(CS<'a>),
+ ERR_UNAVAILRESOURCE(&'a [u8]),
/// 441 ERR_USERNOTINCHANNEL
/// "<nick> <channel> :They aren't on that channel"
@@ -827,7 +893,7 @@ pub enum Reply<'a> {
/// - Returned by the server to indicate that the target
/// user of the command is not on the given channel.
///
- ERR_USERNOTINCHANNEL(CS<'a>),
+ ERR_USERNOTINCHANNEL(&'a [u8]),
/// 442 ERR_NOTONCHANNEL
/// "<channel> :You're not on that channel"
@@ -836,7 +902,7 @@ pub enum Reply<'a> {
/// perform a channel affecting command for which the
/// client isn't a member.
///
- ERR_NOTONCHANNEL(CS<'a>),
+ ERR_NOTONCHANNEL(&'a [u8]),
/// 443 ERR_USERONCHANNEL
/// "<user> <channel> :is already on channel"
@@ -844,7 +910,7 @@ pub enum Reply<'a> {
/// - Returned when a client tries to invite a user to a
/// channel they are already on.
///
- ERR_USERONCHANNEL(CS<'a>),
+ ERR_USERONCHANNEL(&'a [u8]),
/// 444 ERR_NOLOGIN
/// "<user> :User not logged in"
@@ -853,7 +919,7 @@ pub enum Reply<'a> {
/// user was unable to be performed since they were not
/// logged in.
///
- ERR_NOLOGIN(CS<'a>),
+ ERR_NOLOGIN(&'a [u8]),
/// 445 ERR_SUMMONDISABLED
/// ":SUMMON has been disabled"
@@ -861,7 +927,7 @@ pub enum Reply<'a> {
/// - Returned as a response to the SUMMON command. MUST be
/// returned by any server which doesn't implement it.
///
- ERR_SUMMONDISABLED(CS<'a>),
+ ERR_SUMMONDISABLED(&'a [u8]),
/// 446 ERR_USERSDISABLED
/// ":USERS has been disabled"
@@ -869,7 +935,7 @@ pub enum Reply<'a> {
/// - Returned as a response to the USERS command. MUST be
/// returned by any server which does not implement it.
///
- ERR_USERSDISABLED(CS<'a>),
+ ERR_USERSDISABLED(&'a [u8]),
/// 451 ERR_NOTREGISTERED
/// ":You have not registered"
@@ -878,7 +944,7 @@ pub enum Reply<'a> {
/// MUST be registered before the server will allow it
/// to be parsed in detail.
///
- ERR_NOTREGISTERED(CS<'a>),
+ ERR_NOTREGISTERED(&'a [u8]),
/// 461 ERR_NEEDMOREPARAMS
/// "<command> :Not enough parameters"
@@ -887,7 +953,7 @@ pub enum Reply<'a> {
/// indicate to the client that it didn't supply enough
/// parameters.
///
- ERR_NEEDMOREPARAMS(CS<'a>),
+ ERR_NEEDMOREPARAMS(&'a [u8]),
/// 462 ERR_ALREADYREGISTRED
/// ":Unauthorized command (already registered)"
@@ -896,7 +962,7 @@ pub enum Reply<'a> {
/// change part of the registered details (such as
/// password or user details from second USER message).
///
- ERR_ALREADYREGISTRED(CS<'a>),
+ ERR_ALREADYREGISTRED(&'a [u8]),
/// 463 ERR_NOPERMFORHOST
/// ":Your host isn't among the privileged"
@@ -906,7 +972,7 @@ pub enum Reply<'a> {
/// connections from the host the attempted connection
/// is tried.
///
- ERR_NOPERMFORHOST(CS<'a>),
+ ERR_NOPERMFORHOST(&'a [u8]),
/// 464 ERR_PASSWDMISMATCH
/// ":Password incorrect"
@@ -915,7 +981,7 @@ pub enum Reply<'a> {
/// a connection for which a password was required and
/// was either not given or incorrect.
///
- ERR_PASSWDMISMATCH(CS<'a>),
+ ERR_PASSWDMISMATCH(&'a [u8]),
/// 465 ERR_YOUREBANNEDCREEP
/// ":You are banned from this server"
@@ -924,51 +990,51 @@ pub enum Reply<'a> {
/// yourself with a server which has been setup to
/// explicitly deny connections to you.
///
- ERR_YOUREBANNEDCREEP(CS<'a>),
+ ERR_YOUREBANNEDCREEP(&'a [u8]),
/// 466 ERR_YOUWILLBEBANNED
///
/// - Sent by a server to a user to inform that access to the
/// server will soon be denied.
///
- ERR_YOUWILLBEBANNED(CS<'a>),
+ ERR_YOUWILLBEBANNED(&'a [u8]),
/// 467 ERR_KEYSET
/// "<channel> :Channel key already set"
- ERR_KEYSET(CS<'a>),
+ ERR_KEYSET(&'a [u8]),
/// 471 ERR_CHANNELISFULL
/// "<channel> :Cannot join channel (+l)"
- ERR_CHANNELISFULL(CS<'a>),
+ ERR_CHANNELISFULL(&'a [u8]),
/// 472 ERR_UNKNOWNMODE
/// "<char> :is unknown mode char to me for <channel>"
- ERR_UNKNOWNMODE(CS<'a>),
+ ERR_UNKNOWNMODE(&'a [u8]),
/// 473 ERR_INVITEONLYCHAN
/// "<channel> :Cannot join channel (+i)"
- ERR_INVITEONLYCHAN(CS<'a>),
+ ERR_INVITEONLYCHAN(&'a [u8]),
/// 474 ERR_BANNEDFROMCHAN
/// "<channel> :Cannot join channel (+b)"
- ERR_BANNEDFROMCHAN(CS<'a>),
+ ERR_BANNEDFROMCHAN(&'a [u8]),
/// 475 ERR_BADCHANNELKEY
/// "<channel> :Cannot join channel (+k)"
- ERR_BADCHANNELKEY(CS<'a>),
+ ERR_BADCHANNELKEY(&'a [u8]),
/// 476 ERR_BADCHANMASK
/// "<channel> :Bad Channel Mask"
- ERR_BADCHANMASK(CS<'a>),
+ ERR_BADCHANMASK(&'a [u8]),
/// 477 ERR_NOCHANMODES
/// "<channel> :Channel doesn't support modes"
- ERR_NOCHANMODES(CS<'a>),
+ ERR_NOCHANMODES(&'a [u8]),
/// 478 ERR_BANLISTFULL
/// "<channel> <char> :Channel list is full"
///
- ERR_BANLISTFULL(CS<'a>),
+ ERR_BANLISTFULL(&'a [u8]),
/// 481 ERR_NOPRIVILEGES
/// ":Permission Denied- You're not an IRC operator"
@@ -977,7 +1043,7 @@ pub enum Reply<'a> {
/// MUST return this error to indicate the attempt was
/// unsuccessful.
///
- ERR_NOPRIVILEGES(CS<'a>),
+ ERR_NOPRIVILEGES(&'a [u8]),
/// 482 ERR_CHANOPRIVSNEEDED
/// "<channel> :You're not channel operator"
@@ -987,7 +1053,7 @@ pub enum Reply<'a> {
/// making the attempt is not a chanop on the specified
/// channel.
///
- ERR_CHANOPRIVSNEEDED(CS<'a>),
+ ERR_CHANOPRIVSNEEDED(&'a [u8]),
/// 483 ERR_CANTKILLSERVER
/// ":You can't kill a server!"
@@ -996,7 +1062,7 @@ pub enum Reply<'a> {
/// are to be refused and this error returned directly
/// to the client.
///
- ERR_CANTKILLSERVER(CS<'a>),
+ ERR_CANTKILLSERVER(&'a [u8]),
/// 484 ERR_RESTRICTED
/// ":Your connection is restricted!"
@@ -1004,7 +1070,7 @@ pub enum Reply<'a> {
/// - Sent by the server to a user upon connection to indicate
/// the restricted nature of the connection (user mode "+r").
///
- ERR_RESTRICTED(CS<'a>),
+ ERR_RESTRICTED(&'a [u8]),
/// 485 ERR_UNIQOPPRIVSNEEDED
/// ":You're not the original channel operator"
@@ -1013,7 +1079,7 @@ pub enum Reply<'a> {
/// return this error if the client making the attempt is not
/// a chanop on the specified channel.
///
- ERR_UNIQOPPRIVSNEEDED(CS<'a>),
+ ERR_UNIQOPPRIVSNEEDED(&'a [u8]),
/// 491 ERR_NOOPERHOST
/// ":No O-lines for your host"
@@ -1023,7 +1089,7 @@ pub enum Reply<'a> {
/// client's host as an operator, this error MUST be
/// returned.
///
- ERR_NOOPERHOST(CS<'a>),
+ ERR_NOOPERHOST(&'a [u8]),
/// 501 ERR_UMODEUNKNOWNFLAG
/// ":Unknown MODE flag"
@@ -1032,7 +1098,7 @@ pub enum Reply<'a> {
/// message was sent with a nickname parameter and that
/// the a mode flag sent was not recognized.
///
- ERR_UMODEUNKNOWNFLAG(CS<'a>),
+ ERR_UMODEUNKNOWNFLAG(&'a [u8]),
/// 502 ERR_USERSDONTMATCH
/// ":Cannot change mode for other users"
@@ -1040,7 +1106,7 @@ pub enum Reply<'a> {
/// - Error sent to any user trying to view or change the
/// user mode for a user other than themselves.
///
- ERR_USERSDONTMATCH(CS<'a>),
+ ERR_USERSDONTMATCH(&'a [u8]),
}
@@ -1048,12 +1114,12 @@ impl<'a> Reply<'a> {
pub fn from_message(msg: &'a Message) -> Option<Reply<'a>> {
use self::Reply::*;
match msg.command() {
- "001" => msg.elements().last().map(|&e| RPL_WELCOME(Borrowed(e))),
- "002" => msg.elements().last().map(|&e| RPL_YOURHOST(Borrowed(e))),
- "003" => msg.elements().last().map(|&e| RPL_CREATED(Borrowed(e))),
- "004" => msg.elements().last().map(|&e| RPL_MYINFO(Borrowed(e))),
- "005" => msg.elements().last().map(|&e| RPL_BOUNCE(Borrowed(e))),
- "302" => msg.elements().last().map(|&e| RPL_USERHOST(Borrowed(e))),
+ "001" => msg.last().map(|&e| RPL_WELCOME(Borrowed(e))),
+ "002" => msg.last().map(|&e| RPL_YOURHOST(Borrowed(e))),
+ "003" => msg.last().map(|&e| RPL_CREATED(Borrowed(e))),
+ "004" => msg.last().map(|&e| RPL_MYINFO(Borrowed(e))),
+ "005" => msg.last().map(|&e| RPL_BOUNCE(Borrowed(e))),
+ "302" => msg.last().map(|&e| RPL_USERHOST(Borrowed(e))),
"303" => msg.elements().last().map(|&e| RPL_ISON(Borrowed(e))),
"301" => msg.elements().last().map(|&e| RPL_AWAY(Borrowed(e))),
"305" => msg.elements().last().map(|&e| RPL_UNAWAY(Borrowed(e))),
@@ -1192,287 +1258,143 @@ impl<'a> Reply<'a> {
pub fn to_message(&'a self) -> Message {
use self::Reply::*;
match self {
- &RPL_WELCOME(ref s) => Message::format(None, Borrowed("001"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_YOURHOST(ref s) => Message::format(None, Borrowed("002"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_CREATED(ref s) => Message::format(None, Borrowed("003"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_MYINFO(ref s) => Message::format(None, Borrowed("004"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_BOUNCE(ref s) => Message::format(None, Borrowed("005"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_USERHOST(ref s) => Message::format(None, Borrowed("302"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ISON(ref s) => Message::format(None, Borrowed("303"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_AWAY(ref s) => Message::format(None, Borrowed("301"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_UNAWAY(ref s) => Message::format(None, Borrowed("305"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_NOWAWAY(ref s) => Message::format(None, Borrowed("306"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOISUSER(ref s) => Message::format(None, Borrowed("311"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOISSERVER(ref s) => Message::format(None, Borrowed("312"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOISOPERATOR(ref s) => Message::format(None, Borrowed("313"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOISIDLE(ref s) => Message::format(None, Borrowed("317"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFWHOIS(ref s) => Message::format(None, Borrowed("318"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOISCHANNELS(ref s) => Message::format(None, Borrowed("319"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOWASUSER(ref s) => Message::format(None, Borrowed("314"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFWHOWAS(ref s) => Message::format(None, Borrowed("369"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LISTSTART => Message::format(None, Borrowed("321"), vec![], None, MsgType::Irc),
- &RPL_LIST(ref s) => Message::format(None, Borrowed("322"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LISTEND(ref s) => Message::format(None, Borrowed("323"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_UNIQOPIS(ref s) => Message::format(None, Borrowed("325"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_CHANNELMODEIS(ref s) => Message::format(None, Borrowed("324"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_NOTOPIC(ref s) => Message::format(None, Borrowed("331"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TOPIC(ref s) => Message::format(None, Borrowed("332"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_INVITING(ref s) => Message::format(None, Borrowed("341"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_SUMMONING(ref s) => Message::format(None, Borrowed("342"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_INVITELIST(ref s) => Message::format(None, Borrowed("346"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFINVITELIST(ref s) => Message::format(None, Borrowed("347"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_EXCEPTLIST(ref s) => Message::format(None, Borrowed("348"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFEXCEPTLIST(ref s) => Message::format(None, Borrowed("349"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_VERSION(ref s) => Message::format(None, Borrowed("351"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_WHOREPLY(ref s) => Message::format(None, Borrowed("352"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFWHO(ref s) => Message::format(None, Borrowed("315"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_NAMREPLY(ref s) => Message::format(None, Borrowed("353"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFNAMES(ref s) => Message::format(None, Borrowed("366"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LINKS(ref s) => Message::format(None, Borrowed("364"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFLINKS(ref s) => Message::format(None, Borrowed("365"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_BANLIST(ref s) => Message::format(None, Borrowed("367"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFBANLIST(ref s) => Message::format(None, Borrowed("368"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_INFO(ref s) => Message::format(None, Borrowed("371"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFINFO(ref s) => Message::format(None, Borrowed("374"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_MOTDSTART(ref s) => Message::format(None, Borrowed("375"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_MOTD(ref s) => Message::format(None, Borrowed("372"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFMOTD(ref s) => Message::format(None, Borrowed("376"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_YOUREOPER(ref s) => Message::format(None, Borrowed("381"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_REHASHING(ref s) => Message::format(None, Borrowed("382"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_YOURESERVICE(ref s) => Message::format(None, Borrowed("383"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TIME(ref s) => Message::format(None, Borrowed("391"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_USERSSTART(ref s) => Message::format(None, Borrowed("392"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_USERS(ref s) => Message::format(None, Borrowed("393"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFUSERS(ref s) => Message::format(None, Borrowed("394"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_NOUSERS(ref s) => Message::format(None, Borrowed("395"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACELINK(ref s) => Message::format(None, Borrowed("200"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACECONNECTING(ref s) => Message::format(None, Borrowed("201"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACEHANDSHAKE(ref s) => Message::format(None, Borrowed("202"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACEUNKNOWN(ref s) => Message::format(None, Borrowed("203"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACEOPERATOR(ref s) => Message::format(None, Borrowed("204"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACEUSER(ref s) => Message::format(None, Borrowed("205"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACESERVER(ref s) => Message::format(None, Borrowed("206"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACESERVICE(ref s) => Message::format(None, Borrowed("207"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACENEWTYPE(ref s) => Message::format(None, Borrowed("208"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACECLASS(ref s) => Message::format(None, Borrowed("209"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACERECONNECT(ref s) => Message::format(None, Borrowed("210"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACELOG(ref s) => Message::format(None, Borrowed("261"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRACEEND(ref s) => Message::format(None, Borrowed("262"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_STATSLINKINFO(ref s) => Message::format(None, Borrowed("211"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_STATSCOMMANDS(ref s) => Message::format(None, Borrowed("212"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ENDOFSTATS(ref s) => Message::format(None, Borrowed("219"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_STATSUPTIME(ref s) => Message::format(None, Borrowed("242"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_STATSOLINE(ref s) => Message::format(None, Borrowed("243"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_UMODEIS(ref s) => Message::format(None, Borrowed("221"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_SERVLIST(ref s) => Message::format(None, Borrowed("234"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_SERVLISTEND(ref s) => Message::format(None, Borrowed("235"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LUSERCLIENT(ref s) => Message::format(None, Borrowed("251"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LUSEROP(ref s) => Message::format(None, Borrowed("252"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LUSERUNKNOWN(ref s) => Message::format(None, Borrowed("253"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LUSERCHANNELS(ref s) => Message::format(None, Borrowed("254"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_LUSERME(ref s) => Message::format(None, Borrowed("255"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ADMINME(ref s) => Message::format(None, Borrowed("256"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ADMINLOC1(ref s) => Message::format(None, Borrowed("257"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ADMINLOC2(ref s) => Message::format(None, Borrowed("258"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_ADMINEMAIL(ref s) => Message::format(None, Borrowed("259"), vec![], Some(s.clone()), MsgType::Irc),
- &RPL_TRYAGAIN(ref s) => Message::format(None, Borrowed("263"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOSUCHNICK(ref s) => Message::format(None, Borrowed("401"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOSUCHSERVER(ref s) => Message::format(None, Borrowed("402"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOSUCHCHANNEL(ref s) => Message::format(None, Borrowed("403"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_CANNOTSENDTOCHAN(ref s) => Message::format(None, Borrowed("404"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_TOOMANYCHANNELS(ref s) => Message::format(None, Borrowed("405"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_WASNOSUCHNICK(ref s) => Message::format(None, Borrowed("406"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_TOOMANYTARGETS(ref s) => Message::format(None, Borrowed("407"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOSUCHSERVICE(ref s) => Message::format(None, Borrowed("408"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOORIGIN(ref s) => Message::format(None, Borrowed("409"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NORECIPIENT(ref s) => Message::format(None, Borrowed("411"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOTEXTTOSEND(ref s) => Message::format(None, Borrowed("412"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOTOPLEVEL(ref s) => Message::format(None, Borrowed("413"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_WILDTOPLEVEL(ref s) => Message::format(None, Borrowed("414"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_BADMASK(ref s) => Message::format(None, Borrowed("415"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_UNKNOWNCOMMAND(ref s) => Message::format(None, Borrowed("421"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOMOTD(ref s) => Message::format(None, Borrowed("422"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOADMININFO(ref s) => Message::format(None, Borrowed("423"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_FILEERROR(ref s) => Message::format(None, Borrowed("424"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NONICKNAMEGIVEN(ref s) => Message::format(None, Borrowed("431"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_ERRONEUSNICKNAME(ref s) => Message::format(None, Borrowed("432"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NICKNAMEINUSE(ref s) => Message::format(None, Borrowed("433"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NICKCOLLISION(ref s) => Message::format(None, Borrowed("436"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_UNAVAILRESOURCE(ref s) => Message::format(None, Borrowed("437"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_USERNOTINCHANNEL(ref s) => Message::format(None, Borrowed("441"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOTONCHANNEL(ref s) => Message::format(None, Borrowed("442"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_USERONCHANNEL(ref s) => Message::format(None, Borrowed("443"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOLOGIN(ref s) => Message::format(None, Borrowed("444"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_SUMMONDISABLED(ref s) => Message::format(None, Borrowed("445"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_USERSDISABLED(ref s) => Message::format(None, Borrowed("446"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOTREGISTERED(ref s) => Message::format(None, Borrowed("451"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NEEDMOREPARAMS(ref s) => Message::format(None, Borrowed("461"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_ALREADYREGISTRED(ref s) => Message::format(None, Borrowed("462"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOPERMFORHOST(ref s) => Message::format(None, Borrowed("463"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_PASSWDMISMATCH(ref s) => Message::format(None, Borrowed("464"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_YOUREBANNEDCREEP(ref s) => Message::format(None, Borrowed("465"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_YOUWILLBEBANNED(ref s) => Message::format(None, Borrowed("466"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_KEYSET(ref s) => Message::format(None, Borrowed("467"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_CHANNELISFULL(ref s) => Message::format(None, Borrowed("471"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_UNKNOWNMODE(ref s) => Message::format(None, Borrowed("472"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_INVITEONLYCHAN(ref s) => Message::format(None, Borrowed("473"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_BANNEDFROMCHAN(ref s) => Message::format(None, Borrowed("474"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_BADCHANNELKEY(ref s) => Message::format(None, Borrowed("475"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_BADCHANMASK(ref s) => Message::format(None, Borrowed("476"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOCHANMODES(ref s) => Message::format(None, Borrowed("477"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_BANLISTFULL(ref s) => Message::format(None, Borrowed("478"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOPRIVILEGES(ref s) => Message::format(None, Borrowed("481"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_CHANOPRIVSNEEDED(ref s) => Message::format(None, Borrowed("482"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_CANTKILLSERVER(ref s) => Message::format(None, Borrowed("483"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_RESTRICTED(ref s) => Message::format(None, Borrowed("484"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_UNIQOPPRIVSNEEDED(ref s) => Message::format(None, Borrowed("485"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_NOOPERHOST(ref s) => Message::format(None, Borrowed("491"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_UMODEUNKNOWNFLAG(ref s) => Message::format(None, Borrowed("501"), vec![], Some(s.clone()), MsgType::Irc),
- &ERR_USERSDONTMATCH(ref s) => Message::format(None, Borrowed("502"), vec![], Some(s.clone()), MsgType::Irc),
+ &RPL_WELCOME(ref s) => Message::format(None, Borrowed("001"), vec![], s),
+ &RPL_YOURHOST(ref s) => Message::format(None, Borrowed("002"), vec![], s),
+ &RPL_CREATED(ref s) => Message::format(None, Borrowed("003"), vec![], s),
+ &RPL_MYINFO(ref s) => Message::format(None, Borrowed("004"), vec![], s),
+ &RPL_BOUNCE(ref s) => Message::format(None, Borrowed("005"), vec![], s),
+ &RPL_USERHOST(ref s) => Message::format(None, Borrowed("302"), vec![], s),
+ &RPL_ISON(ref s) => Message::format(None, Borrowed("303"), vec![], s),
+ &RPL_AWAY(ref s) => Message::format(None, Borrowed("301"), vec![], s),
+ &RPL_UNAWAY(ref s) => Message::format(None, Borrowed("305"), vec![], s),
+ &RPL_NOWAWAY(ref s) => Message::format(None, Borrowed("306"), vec![], s),
+ &RPL_WHOISUSER(ref s) => Message::format(None, Borrowed("311"), vec![], s),
+ &RPL_WHOISSERVER(ref s) => Message::format(None, Borrowed("312"), vec![], s),
+ &RPL_WHOISOPERATOR(ref s) => Message::format(None, Borrowed("313"), vec![], s),
+ &RPL_WHOISIDLE(ref s) => Message::format(None, Borrowed("317"), vec![], s),
+ &RPL_ENDOFWHOIS(ref s) => Message::format(None, Borrowed("318"), vec![], s),
+ &RPL_WHOISCHANNELS(ref s) => Message::format(None, Borrowed("319"), vec![], s),
+ &RPL_WHOWASUSER(ref s) => Message::format(None, Borrowed("314"), vec![], s),
+ &RPL_ENDOFWHOWAS(ref s) => Message::format(None, Borrowed("369"), vec![], s),
+ &RPL_LISTSTART => Message::format(None, Borrowed("321"), vec![], None),
+ &RPL_LIST(ref s) => Message::format(None, Borrowed("322"), vec![], s),
+ &RPL_LISTEND(ref s) => Message::format(None, Borrowed("323"), vec![], s),
+ &RPL_UNIQOPIS(ref s) => Message::format(None, Borrowed("325"), vec![], s),
+ &RPL_CHANNELMODEIS(ref s) => Message::format(None, Borrowed("324"), vec![], s),
+ &RPL_NOTOPIC(ref s) => Message::format(None, Borrowed("331"), vec![], s),
+ &RPL_TOPIC(ref s) => Message::format(None, Borrowed("332"), vec![], s),
+ &RPL_INVITING(ref s) => Message::format(None, Borrowed("341"), vec![], s),
+ &RPL_SUMMONING(ref s) => Message::format(None, Borrowed("342"), vec![], s),
+ &RPL_INVITELIST(ref s) => Message::format(None, Borrowed("346"), vec![], s),
+ &RPL_ENDOFINVITELIST(ref s) => Message::format(None, Borrowed("347"), vec![], s),
+ &RPL_EXCEPTLIST(ref s) => Message::format(None, Borrowed("348"), vec![], s),
+ &RPL_ENDOFEXCEPTLIST(ref s) => Message::format(None, Borrowed("349"), vec![], s),
+ &RPL_VERSION(ref s) => Message::format(None, Borrowed("351"), vec![], s),
+ &RPL_WHOREPLY(ref s) => Message::format(None, Borrowed("352"), vec![], s),
+ &RPL_ENDOFWHO(ref s) => Message::format(None, Borrowed("315"), vec![], s),
+ &RPL_NAMREPLY(ref s) => Message::format(None, Borrowed("353"), vec![], s),
+ &RPL_ENDOFNAMES(ref s) => Message::format(None, Borrowed("366"), vec![], s),
+ &RPL_LINKS(ref s) => Message::format(None, Borrowed("364"), vec![], s),
+ &RPL_ENDOFLINKS(ref s) => Message::format(None, Borrowed("365"), vec![], s),
+ &RPL_BANLIST(ref s) => Message::format(None, Borrowed("367"), vec![], s),
+ &RPL_ENDOFBANLIST(ref s) => Message::format(None, Borrowed("368"), vec![], s),
+ &RPL_INFO(ref s) => Message::format(None, Borrowed("371"), vec![], s),
+ &RPL_ENDOFINFO(ref s) => Message::format(None, Borrowed("374"), vec![], s),
+ &RPL_MOTDSTART(ref s) => Message::format(None, Borrowed("375"), vec![], s),
+ &RPL_MOTD(ref s) => Message::format(None, Borrowed("372"), vec![], s),
+ &RPL_ENDOFMOTD(ref s) => Message::format(None, Borrowed("376"), vec![], s),
+ &RPL_YOUREOPER(ref s) => Message::format(None, Borrowed("381"), vec![], s),
+ &RPL_REHASHING(ref s) => Message::format(None, Borrowed("382"), vec![], s),
+ &RPL_YOURESERVICE(ref s) => Message::format(None, Borrowed("383"), vec![], s),
+ &RPL_TIME(ref s) => Message::format(None, Borrowed("391"), vec![], s),
+ &RPL_USERSSTART(ref s) => Message::format(None, Borrowed("392"), vec![], s),
+ &RPL_USERS(ref s) => Message::format(None, Borrowed("393"), vec![], s),
+ &RPL_ENDOFUSERS(ref s) => Message::format(None, Borrowed("394"), vec![], s),
+ &RPL_NOUSERS(ref s) => Message::format(None, Borrowed("395"), vec![], s),
+ &RPL_TRACELINK(ref s) => Message::format(None, Borrowed("200"), vec![], s),
+ &RPL_TRACECONNECTING(ref s) => Message::format(None, Borrowed("201"), vec![], s),
+ &RPL_TRACEHANDSHAKE(ref s) => Message::format(None, Borrowed("202"), vec![], s),
+ &RPL_TRACEUNKNOWN(ref s) => Message::format(None, Borrowed("203"), vec![], s),
+ &RPL_TRACEOPERATOR(ref s) => Message::format(None, Borrowed("204"), vec![], s),
+ &RPL_TRACEUSER(ref s) => Message::format(None, Borrowed("205"), vec![], s),
+ &RPL_TRACESERVER(ref s) => Message::format(None, Borrowed("206"), vec![], s),
+ &RPL_TRACESERVICE(ref s) => Message::format(None, Borrowed("207"), vec![], s),
+ &RPL_TRACENEWTYPE(ref s) => Message::format(None, Borrowed("208"), vec![], s),
+ &RPL_TRACECLASS(ref s) => Message::format(None, Borrowed("209"), vec![], s),
+ &RPL_TRACERECONNECT(ref s) => Message::format(None, Borrowed("210"), vec![], s),
+ &RPL_TRACELOG(ref s) => Message::format(None, Borrowed("261"), vec![], s),
+ &RPL_TRACEEND(ref s) => Message::format(None, Borrowed("262"), vec![], s),
+ &RPL_STATSLINKINFO(ref s) => Message::format(None, Borrowed("211"), vec![], s),
+ &RPL_STATSCOMMANDS(ref s) => Message::format(None, Borrowed("212"), vec![], s),
+ &RPL_ENDOFSTATS(ref s) => Message::format(None, Borrowed("219"), vec![], s),
+ &RPL_STATSUPTIME(ref s) => Message::format(None, Borrowed("242"), vec![], s),
+ &RPL_STATSOLINE(ref s) => Message::format(None, Borrowed("243"), vec![], s),
+ &RPL_UMODEIS(ref s) => Message::format(None, Borrowed("221"), vec![], s),
+ &RPL_SERVLIST(ref s) => Message::format(None, Borrowed("234"), vec![], s),
+ &RPL_SERVLISTEND(ref s) => Message::format(None, Borrowed("235"), vec![], s),
+ &RPL_LUSERCLIENT(ref s) => Message::format(None, Borrowed("251"), vec![], s),
+ &RPL_LUSEROP(ref s) => Message::format(None, Borrowed("252"), vec![], s),
+ &RPL_LUSERUNKNOWN(ref s) => Message::format(None, Borrowed("253"), vec![], s),
+ &RPL_LUSERCHANNELS(ref s) => Message::format(None, Borrowed("254"), vec![], s),
+ &RPL_LUSERME(ref s) => Message::format(None, Borrowed("255"), vec![], s),
+ &RPL_ADMINME(ref s) => Message::format(None, Borrowed("256"), vec![], s),
+ &RPL_ADMINLOC1(ref s) => Message::format(None, Borrowed("257"), vec![], s),
+ &RPL_ADMINLOC2(ref s) => Message::format(None, Borrowed("258"), vec![], s),
+ &RPL_ADMINEMAIL(ref s) => Message::format(None, Borrowed("259"), vec![], s),
+ &RPL_TRYAGAIN(ref s) => Message::format(None, Borrowed("263"), vec![], s),
+ &ERR_NOSUCHNICK(ref s) => Message::format(None, Borrowed("401"), vec![], s),
+ &ERR_NOSUCHSERVER(ref s) => Message::format(None, Borrowed("402"), vec![], s),
+ &ERR_NOSUCHCHANNEL(ref s) => Message::format(None, Borrowed("403"), vec![], s),
+ &ERR_CANNOTSENDTOCHAN(ref s) => Message::format(None, Borrowed("404"), vec![], s),
+ &ERR_TOOMANYCHANNELS(ref s) => Message::format(None, Borrowed("405"), vec![], s),
+ &ERR_WASNOSUCHNICK(ref s) => Message::format(None, Borrowed("406"), vec![], s),
+ &ERR_TOOMANYTARGETS(ref s) => Message::format(None, Borrowed("407"), vec![], s),
+ &ERR_NOSUCHSERVICE(ref s) => Message::format(None, Borrowed("408"), vec![], s),
+ &ERR_NOORIGIN(ref s) => Message::format(None, Borrowed("409"), vec![], s),
+ &ERR_NORECIPIENT(ref s) => Message::format(None, Borrowed("411"), vec![], s),
+ &ERR_NOTEXTTOSEND(ref s) => Message::format(None, Borrowed("412"), vec![], s),
+ &ERR_NOTOPLEVEL(ref s) => Message::format(None, Borrowed("413"), vec![], s),
+ &ERR_WILDTOPLEVEL(ref s) => Message::format(None, Borrowed("414"), vec![], s),
+ &ERR_BADMASK(ref s) => Message::format(None, Borrowed("415"), vec![], s),
+ &ERR_UNKNOWNCOMMAND(ref s) => Message::format(None, Borrowed("421"), vec![], s),
+ &ERR_NOMOTD(ref s) => Message::format(None, Borrowed("422"), vec![], s),
+ &ERR_NOADMININFO(ref s) => Message::format(None, Borrowed("423"), vec![], s),
+ &ERR_FILEERROR(ref s) => Message::format(None, Borrowed("424"), vec![], s),
+ &ERR_NONICKNAMEGIVEN(ref s) => Message::format(None, Borrowed("431"), vec![], s),
+ &ERR_ERRONEUSNICKNAME(ref s) => Message::format(None, Borrowed("432"), vec![], s),
+ &ERR_NICKNAMEINUSE(ref s) => Message::format(None, Borrowed("433"), vec![], s),
+ &ERR_NICKCOLLISION(ref s) => Message::format(None, Borrowed("436"), vec![], s),
+ &ERR_UNAVAILRESOURCE(ref s) => Message::format(None, Borrowed("437"), vec![], s),
+ &ERR_USERNOTINCHANNEL(ref s) => Message::format(None, Borrowed("441"), vec![], s),
+ &ERR_NOTONCHANNEL(ref s) => Message::format(None, Borrowed("442"), vec![], s),
+ &ERR_USERONCHANNEL(ref s) => Message::format(None, Borrowed("443"), vec![], s),
+ &ERR_NOLOGIN(ref s) => Message::format(None, Borrowed("444"), vec![], s),
+ &ERR_SUMMONDISABLED(ref s) => Message::format(None, Borrowed("445"), vec![], s),
+ &ERR_USERSDISABLED(ref s) => Message::format(None, Borrowed("446"), vec![], s),
+ &ERR_NOTREGISTERED(ref s) => Message::format(None, Borrowed("451"), vec![], s),
+ &ERR_NEEDMOREPARAMS(ref s) => Message::format(None, Borrowed("461"), vec![], s),
+ &ERR_ALREADYREGISTRED(ref s) => Message::format(None, Borrowed("462"), vec![], s),
+ &ERR_NOPERMFORHOST(ref s) => Message::format(None, Borrowed("463"), vec![], s),
+ &ERR_PASSWDMISMATCH(ref s) => Message::format(None, Borrowed("464"), vec![], s),
+ &ERR_YOUREBANNEDCREEP(ref s) => Message::format(None, Borrowed("465"), vec![], s),
+ &ERR_YOUWILLBEBANNED(ref s) => Message::format(None, Borrowed("466"), vec![], s),
+ &ERR_KEYSET(ref s) => Message::format(None, Borrowed("467"), vec![], s),
+ &ERR_CHANNELISFULL(ref s) => Message::format(None, Borrowed("471"), vec![], s),
+ &ERR_UNKNOWNMODE(ref s) => Message::format(None, Borrowed("472"), vec![], s),
+ &ERR_INVITEONLYCHAN(ref s) => Message::format(None, Borrowed("473"), vec![], s),
+ &ERR_BANNEDFROMCHAN(ref s) => Message::format(None, Borrowed("474"), vec![], s),
+ &ERR_BADCHANNELKEY(ref s) => Message::format(None, Borrowed("475"), vec![], s),
+ &ERR_BADCHANMASK(ref s) => Message::format(None, Borrowed("476"), vec![], s),
+ &ERR_NOCHANMODES(ref s) => Message::format(None, Borrowed("477"), vec![], s),
+ &ERR_BANLISTFULL(ref s) => Message::format(None, Borrowed("478"), vec![], s),
+ &ERR_NOPRIVILEGES(ref s) => Message::format(None, Borrowed("481"), vec![], s),
+ &ERR_CHANOPRIVSNEEDED(ref s) => Message::format(None, Borrowed("482"), vec![], s),
+ &ERR_CANTKILLSERVER(ref s) => Message::format(None, Borrowed("483"), vec![], s),
+ &ERR_RESTRICTED(ref s) => Message::format(None, Borrowed("484"), vec![], s),
+ &ERR_UNIQOPPRIVSNEEDED(ref s) => Message::format(None, Borrowed("485"), vec![], s),
+ &ERR_NOOPERHOST(ref s) => Message::format(None, Borrowed("491"), vec![], s),
+ &ERR_UMODEUNKNOWNFLAG(ref s) => Message::format(None, Borrowed("501"), vec![], s),
+ &ERR_USERSDONTMATCH(ref s) => Message::format(None, Borrowed("502"), vec![], s),
}
}
-
- pub fn to_static(&self) -> Reply<'static> {
- use self::Reply::*;
- match self {
- &RPL_WELCOME(ref s) => RPL_WELCOME(Cow::Owned(s.clone().into_owned())),
- &RPL_YOURHOST(ref s) => RPL_YOURHOST(Cow::Owned(s.clone().into_owned())),
- &RPL_CREATED(ref s) => RPL_CREATED(Cow::Owned(s.clone().into_owned())),
- &RPL_MYINFO(ref s) => RPL_MYINFO(Cow::Owned(s.clone().into_owned())),
- &RPL_BOUNCE(ref s) => RPL_BOUNCE(Cow::Owned(s.clone().into_owned())),
- &RPL_USERHOST(ref s) => RPL_USERHOST(Cow::Owned(s.clone().into_owned())),
- &RPL_ISON(ref s) => RPL_ISON(Cow::Owned(s.clone().into_owned())),
- &RPL_AWAY(ref s) => RPL_AWAY(Cow::Owned(s.clone().into_owned())),
- &RPL_UNAWAY(ref s) => RPL_UNAWAY(Cow::Owned(s.clone().into_owned())),
- &RPL_NOWAWAY(ref s) => RPL_NOWAWAY(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOISUSER(ref s) => RPL_WHOISUSER(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOISSERVER(ref s) => RPL_WHOISSERVER(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOISOPERATOR(ref s) => RPL_WHOISOPERATOR(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOISIDLE(ref s) => RPL_WHOISIDLE(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFWHOIS(ref s) => RPL_ENDOFWHOIS(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOISCHANNELS(ref s) => RPL_WHOISCHANNELS(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOWASUSER(ref s) => RPL_WHOWASUSER(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFWHOWAS(ref s) => RPL_ENDOFWHOWAS(Cow::Owned(s.clone().into_owned())),
- &RPL_LISTSTART => RPL_LISTSTART,
- &RPL_LIST(ref s) => RPL_LIST(Cow::Owned(s.clone().into_owned())),
- &RPL_LISTEND(ref s) => RPL_LISTEND(Cow::Owned(s.clone().into_owned())),
- &RPL_UNIQOPIS(ref s) => RPL_UNIQOPIS(Cow::Owned(s.clone().into_owned())),
- &RPL_CHANNELMODEIS(ref s) => RPL_CHANNELMODEIS(Cow::Owned(s.clone().into_owned())),
- &RPL_NOTOPIC(ref s) => RPL_NOTOPIC(Cow::Owned(s.clone().into_owned())),
- &RPL_TOPIC(ref s) => RPL_TOPIC(Cow::Owned(s.clone().into_owned())),
- &RPL_INVITING(ref s) => RPL_INVITING(Cow::Owned(s.clone().into_owned())),
- &RPL_SUMMONING(ref s) => RPL_SUMMONING(Cow::Owned(s.clone().into_owned())),
- &RPL_INVITELIST(ref s) => RPL_INVITELIST(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFINVITELIST(ref s) => RPL_ENDOFINVITELIST(Cow::Owned(s.clone().into_owned())),
- &RPL_EXCEPTLIST(ref s) => RPL_EXCEPTLIST(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFEXCEPTLIST(ref s) => RPL_ENDOFEXCEPTLIST(Cow::Owned(s.clone().into_owned())),
- &RPL_VERSION(ref s) => RPL_VERSION(Cow::Owned(s.clone().into_owned())),
- &RPL_WHOREPLY(ref s) => RPL_WHOREPLY(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFWHO(ref s) => RPL_ENDOFWHO(Cow::Owned(s.clone().into_owned())),
- &RPL_NAMREPLY(ref s) => RPL_NAMREPLY(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFNAMES(ref s) => RPL_ENDOFNAMES(Cow::Owned(s.clone().into_owned())),
- &RPL_LINKS(ref s) => RPL_LINKS(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFLINKS(ref s) => RPL_ENDOFLINKS(Cow::Owned(s.clone().into_owned())),
- &RPL_BANLIST(ref s) => RPL_BANLIST(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFBANLIST(ref s) => RPL_ENDOFBANLIST(Cow::Owned(s.clone().into_owned())),
- &RPL_INFO(ref s) => RPL_INFO(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFINFO(ref s) => RPL_ENDOFINFO(Cow::Owned(s.clone().into_owned())),
- &RPL_MOTDSTART(ref s) => RPL_MOTDSTART(Cow::Owned(s.clone().into_owned())),
- &RPL_MOTD(ref s) => RPL_MOTD(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFMOTD(ref s) => RPL_ENDOFMOTD(Cow::Owned(s.clone().into_owned())),
- &RPL_YOUREOPER(ref s) => RPL_YOUREOPER(Cow::Owned(s.clone().into_owned())),
- &RPL_REHASHING(ref s) => RPL_REHASHING(Cow::Owned(s.clone().into_owned())),
- &RPL_YOURESERVICE(ref s) => RPL_YOURESERVICE(Cow::Owned(s.clone().into_owned())),
- &RPL_TIME(ref s) => RPL_TIME(Cow::Owned(s.clone().into_owned())),
- &RPL_USERSSTART(ref s) => RPL_USERSSTART(Cow::Owned(s.clone().into_owned())),
- &RPL_USERS(ref s) => RPL_USERS(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFUSERS(ref s) => RPL_ENDOFUSERS(Cow::Owned(s.clone().into_owned())),
- &RPL_NOUSERS(ref s) => RPL_NOUSERS(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACELINK(ref s) => RPL_TRACELINK(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACECONNECTING(ref s) => RPL_TRACECONNECTING(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACEHANDSHAKE(ref s) => RPL_TRACEHANDSHAKE(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACEUNKNOWN(ref s) => RPL_TRACEUNKNOWN(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACEOPERATOR(ref s) => RPL_TRACEOPERATOR(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACEUSER(ref s) => RPL_TRACEUSER(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACESERVER(ref s) => RPL_TRACESERVER(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACESERVICE(ref s) => RPL_TRACESERVICE(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACENEWTYPE(ref s) => RPL_TRACENEWTYPE(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACECLASS(ref s) => RPL_TRACECLASS(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACERECONNECT(ref s) => RPL_TRACERECONNECT(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACELOG(ref s) => RPL_TRACELOG(Cow::Owned(s.clone().into_owned())),
- &RPL_TRACEEND(ref s) => RPL_TRACEEND(Cow::Owned(s.clone().into_owned())),
- &RPL_STATSLINKINFO(ref s) => RPL_STATSLINKINFO(Cow::Owned(s.clone().into_owned())),
- &RPL_STATSCOMMANDS(ref s) => RPL_STATSCOMMANDS(Cow::Owned(s.clone().into_owned())),
- &RPL_ENDOFSTATS(ref s) => RPL_ENDOFSTATS(Cow::Owned(s.clone().into_owned())),
- &RPL_STATSUPTIME(ref s) => RPL_STATSUPTIME(Cow::Owned(s.clone().into_owned())),
- &RPL_STATSOLINE(ref s) => RPL_STATSOLINE(Cow::Owned(s.clone().into_owned())),
- &RPL_UMODEIS(ref s) => RPL_UMODEIS(Cow::Owned(s.clone().into_owned())),
- &RPL_SERVLIST(ref s) => RPL_SERVLIST(Cow::Owned(s.clone().into_owned())),
- &RPL_SERVLISTEND(ref s) => RPL_SERVLISTEND(Cow::Owned(s.clone().into_owned())),
- &RPL_LUSERCLIENT(ref s) => RPL_LUSERCLIENT(Cow::Owned(s.clone().into_owned())),
- &RPL_LUSEROP(ref s) => RPL_LUSEROP(Cow::Owned(s.clone().into_owned())),
- &RPL_LUSERUNKNOWN(ref s) => RPL_LUSERUNKNOWN(Cow::Owned(s.clone().into_owned())),
- &RPL_LUSERCHANNELS(ref s) => RPL_LUSERCHANNELS(Cow::Owned(s.clone().into_owned())),
- &RPL_LUSERME(ref s) => RPL_LUSERME(Cow::Owned(s.clone().into_owned())),
- &RPL_ADMINME(ref s) => RPL_ADMINME(Cow::Owned(s.clone().into_owned())),
- &RPL_ADMINLOC1(ref s) => RPL_ADMINLOC1(Cow::Owned(s.clone().into_owned())),
- &RPL_ADMINLOC2(ref s) => RPL_ADMINLOC2(Cow::Owned(s.clone().into_owned())),
- &RPL_ADMINEMAIL(ref s) => RPL_ADMINEMAIL(Cow::Owned(s.clone().into_owned())),
- &RPL_TRYAGAIN(ref s) => RPL_TRYAGAIN(Cow::Owned(s.clone().into_owned())),
- &ERR_NOSUCHNICK(ref s) => ERR_NOSUCHNICK(Cow::Owned(s.clone().into_owned())),
- &ERR_NOSUCHSERVER(ref s) => ERR_NOSUCHSERVER(Cow::Owned(s.clone().into_owned())),
- &ERR_NOSUCHCHANNEL(ref s) => ERR_NOSUCHCHANNEL(Cow::Owned(s.clone().into_owned())),
- &ERR_CANNOTSENDTOCHAN(ref s) => ERR_CANNOTSENDTOCHAN(Cow::Owned(s.clone().into_owned())),
- &ERR_TOOMANYCHANNELS(ref s) => ERR_TOOMANYCHANNELS(Cow::Owned(s.clone().into_owned())),
- &ERR_WASNOSUCHNICK(ref s) => ERR_WASNOSUCHNICK(Cow::Owned(s.clone().into_owned())),
- &ERR_TOOMANYTARGETS(ref s) => ERR_TOOMANYTARGETS(Cow::Owned(s.clone().into_owned())),
- &ERR_NOSUCHSERVICE(ref s) => ERR_NOSUCHSERVICE(Cow::Owned(s.clone().into_owned())),
- &ERR_NOORIGIN(ref s) => ERR_NOORIGIN(Cow::Owned(s.clone().into_owned())),
- &ERR_NORECIPIENT(ref s) => ERR_NORECIPIENT(Cow::Owned(s.clone().into_owned())),
- &ERR_NOTEXTTOSEND(ref s) => ERR_NOTEXTTOSEND(Cow::Owned(s.clone().into_owned())),
- &ERR_NOTOPLEVEL(ref s) => ERR_NOTOPLEVEL(Cow::Owned(s.clone().into_owned())),
- &ERR_WILDTOPLEVEL(ref s) => ERR_WILDTOPLEVEL(Cow::Owned(s.clone().into_owned())),
- &ERR_BADMASK(ref s) => ERR_BADMASK(Cow::Owned(s.clone().into_owned())),
- &ERR_UNKNOWNCOMMAND(ref s) => ERR_UNKNOWNCOMMAND(Cow::Owned(s.clone().into_owned())),
- &ERR_NOMOTD(ref s) => ERR_NOMOTD(Cow::Owned(s.clone().into_owned())),
- &ERR_NOADMININFO(ref s) => ERR_NOADMININFO(Cow::Owned(s.clone().into_owned())),
- &ERR_FILEERROR(ref s) => ERR_FILEERROR(Cow::Owned(s.clone().into_owned())),
- &ERR_NONICKNAMEGIVEN(ref s) => ERR_NONICKNAMEGIVEN(Cow::Owned(s.clone().into_owned())),
- &ERR_ERRONEUSNICKNAME(ref s) => ERR_ERRONEUSNICKNAME(Cow::Owned(s.clone().into_owned())),
- &ERR_NICKNAMEINUSE(ref s) => ERR_NICKNAMEINUSE(Cow::Owned(s.clone().into_owned())),
- &ERR_NICKCOLLISION(ref s) => ERR_NICKCOLLISION(Cow::Owned(s.clone().into_owned())),
- &ERR_UNAVAILRESOURCE(ref s) => ERR_UNAVAILRESOURCE(Cow::Owned(s.clone().into_owned())),
- &ERR_USERNOTINCHANNEL(ref s) => ERR_USERNOTINCHANNEL(Cow::Owned(s.clone().into_owned())),
- &ERR_NOTONCHANNEL(ref s) => ERR_NOTONCHANNEL(Cow::Owned(s.clone().into_owned())),
- &ERR_USERONCHANNEL(ref s) => ERR_USERONCHANNEL(Cow::Owned(s.clone().into_owned())),
- &ERR_NOLOGIN(ref s) => ERR_NOLOGIN(Cow::Owned(s.clone().into_owned())),
- &ERR_SUMMONDISABLED(ref s) => ERR_SUMMONDISABLED(Cow::Owned(s.clone().into_owned())),
- &ERR_USERSDISABLED(ref s) => ERR_USERSDISABLED(Cow::Owned(s.clone().into_owned())),
- &ERR_NOTREGISTERED(ref s) => ERR_NOTREGISTERED(Cow::Owned(s.clone().into_owned())),
- &ERR_NEEDMOREPARAMS(ref s) => ERR_NEEDMOREPARAMS(Cow::Owned(s.clone().into_owned())),
- &ERR_ALREADYREGISTRED(ref s) => ERR_ALREADYREGISTRED(Cow::Owned(s.clone().into_owned())),
- &ERR_NOPERMFORHOST(ref s) => ERR_NOPERMFORHOST(Cow::Owned(s.clone().into_owned())),
- &ERR_PASSWDMISMATCH(ref s) => ERR_PASSWDMISMATCH(Cow::Owned(s.clone().into_owned())),
- &ERR_YOUREBANNEDCREEP(ref s) => ERR_YOUREBANNEDCREEP(Cow::Owned(s.clone().into_owned())),
- &ERR_YOUWILLBEBANNED(ref s) => ERR_YOUWILLBEBANNED(Cow::Owned(s.clone().into_owned())),
- &ERR_KEYSET(ref s) => ERR_KEYSET(Cow::Owned(s.clone().into_owned())),
- &ERR_CHANNELISFULL(ref s) => ERR_CHANNELISFULL(Cow::Owned(s.clone().into_owned())),
- &ERR_UNKNOWNMODE(ref s) => ERR_UNKNOWNMODE(Cow::Owned(s.clone().into_owned())),
- &ERR_INVITEONLYCHAN(ref s) => ERR_INVITEONLYCHAN(Cow::Owned(s.clone().into_owned())),
- &ERR_BANNEDFROMCHAN(ref s) => ERR_BANNEDFROMCHAN(Cow::Owned(s.clone().into_owned())),
- &ERR_BADCHANNELKEY(ref s) => ERR_BADCHANNELKEY(Cow::Owned(s.clone().into_owned())),
- &ERR_BADCHANMASK(ref s) => ERR_BADCHANMASK(Cow::Owned(s.clone().into_owned())),
- &ERR_NOCHANMODES(ref s) => ERR_NOCHANMODES(Cow::Owned(s.clone().into_owned())),
- &ERR_BANLISTFULL(ref s) => ERR_BANLISTFULL(Cow::Owned(s.clone().into_owned())),
- &ERR_NOPRIVILEGES(ref s) => ERR_NOPRIVILEGES(Cow::Owned(s.clone().into_owned())),
- &ERR_CHANOPRIVSNEEDED(ref s) => ERR_CHANOPRIVSNEEDED(Cow::Owned(s.clone().into_owned())),
- &ERR_CANTKILLSERVER(ref s) => ERR_CANTKILLSERVER(Cow::Owned(s.clone().into_owned())),
- &ERR_RESTRICTED(ref s) => ERR_RESTRICTED(Cow::Owned(s.clone().into_owned())),
- &ERR_UNIQOPPRIVSNEEDED(ref s) => ERR_UNIQOPPRIVSNEEDED(Cow::Owned(s.clone().into_owned())),
- &ERR_NOOPERHOST(ref s) => ERR_NOOPERHOST(Cow::Owned(s.clone().into_owned())),
- &ERR_UMODEUNKNOWNFLAG(ref s) => ERR_UMODEUNKNOWNFLAG(Cow::Owned(s.clone().into_owned())),
- &ERR_USERSDONTMATCH(ref s) => ERR_USERSDONTMATCH(Cow::Owned(s.clone().into_owned())),
- }
-
- }
-}
+}*/
diff --git a/src/text.rs b/src/text.rs
new file mode 100644
index 0000000..98da9b8
--- /dev/null
+++ b/src/text.rs
@@ -0,0 +1,196 @@
+use encoding::types::{ DecoderTrap, EncodingRef };
+use encoding::all::encodings;
+
+use std::ops::{ Range, Deref, Index };
+use std::borrow::Borrow;
+use std::fmt;
+
+// shorthand-exports for construction
+pub use self::Text::Raw as tr;
+pub use self::Text::Utf8 as tu;
+pub use self::TextSlice::Raw as tsr;
+pub use self::TextSlice::Utf8 as tsu;
+
+/// Safe wrapper around something that's supposed to represent text.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub enum Text {
+ Raw(Vec<u8>),
+ Utf8(String),
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub enum TextSlice<'a> {
+ Raw(&'a [u8]),
+ Utf8(&'a str)
+}
+
+pub const EMPTY_RAW: TextSlice<'static> = TextSlice::Raw(&[]);
+pub const EMPTY_UTF8: TextSlice<'static> = TextSlice::Utf8("");
+
+impl Text {
+ pub fn decode_with(&self, e: EncodingRef, d: DecoderTrap) -> Text {
+ match self {
+ &Text::Raw(b) => match e.decode(&b, d) {
+ Ok(s) => Text::Utf8(s),
+ Err(_) => Text::Raw(b)
+ },
+ &Text::Utf8(s) => Text::Utf8(s)
+ }
+ }
+
+ pub fn try_decode_with(&self, e: EncodingRef) -> Text {
+ self.decode_with(DecoderTrap::Strict)
+ }
+
+ pub fn try_decode_as(&self, e: &str) -> Option<Text> {
+ encoding(e).map(|e| self.try_decode_with(e))
+ }
+
+ pub fn lossy_decode_with(&self, e: EncodingRef) -> Text {
+ self.decode_with(DecoderTrap::Replace)
+ }
+
+ pub fn lossy_decode_as(&self, e: &str) -> Option<Text> {
+ encoding(e).map(|e| self.lossy_decode_with(e))
+ }
+
+ pub fn raw(&self) -> Option<&[u8]> {
+ match self {
+ &Text::Raw(ref b) => Some(b),
+ _ => None
+ }
+ }
+
+ pub fn utf8(&self) -> Option<&str> {
+ match self {
+ &Text::Utf8(ref s) => Some(s),
+ _ => None
+ }
+ }
+
+ pub fn slice<'a>(&'a self, r: &Range<usize>) -> TextSlice<'a> {
+ match self {
+ &Text::Raw(ref b) => TextSlice::Raw(&b[r]),
+ &Text::Utf8(ref s) => TextSlice::Utf8(&s[r])
+ }
+ }
+
+ pub fn length(&self) -> usize {
+ match self {
+ &Text::Raw(ref b) => b.len(),
+ &Text::Utf8(ref s) => s.len()
+ }
+ }
+}
+
+impl<'a> TextSlice<'a> {
+ pub fn raw(&self) -> Option<&[u8]> {
+ match self {
+ &TextSlice::Raw(ref b) => Some(b),
+ _ => None
+ }
+ }
+
+ pub fn utf8(&self) -> Option<&str> {
+ match self {
+ &TextSlice::Utf8(ref s) => Some(s),
+ _ => None
+ }
+ }
+}
+
+impl<'a> From<TextSlice<'a>> for Text {
+ fn from(ts: TextSlice<'a>) -> Text {
+ match ts {
+ TextSlice::Raw(b) => Text::Raw(b.into()),
+ TextSlice::Utf8(s) => Text::Utf8(s.into())
+ }
+ }
+}
+
+impl<'a> From<&'a Text> for TextSlice<'a> {
+ fn from(t: &'a Text) -> TextSlice<'a> {
+ match t {
+ &Text::Raw(ref b) => TextSlice::Raw(b),
+ &Text::Utf8(ref s) => TextSlice::Utf8(s)
+ }
+ }
+}
+
+impl<'a> From<&'a str> for Text {
+ fn from(s: &'a str) -> Text {
+ Text::Utf8(s.into())
+ }
+}
+
+impl<'a> From<&'a [u8]> for Text {
+ fn from(b: &'a [u8]) -> Text {
+ Text::Raw(b.into())
+ }
+}
+
+impl<'a> From<&'a str> for TextSlice<'a> {
+ fn from(s: &'a str) -> TextSlice<'a> {
+ TextSlice::Utf8(s)
+ }
+}
+
+impl<'a> From<&'a [u8]> for TextSlice<'a> {
+ fn from(b: &'a [u8]) -> TextSlice<'a> {
+ TextSlice::Raw(b)
+ }
+}
+
+
+impl<'a> Deref for TextSlice<'a> {
+ type Target = [u8];
+ fn deref(&self) -> &[u8] {
+ match self {
+ &Text::Raw(ref b) => b,
+ &Text::Utf8(ref s) => s.as_bytes()
+ }
+ }
+}
+
+impl Deref for Text {
+ type Target = [u8];
+ fn deref(&self) -> &[u8] {
+ match self {
+ &Text::Raw(ref b) => b,
+ &Text::Utf8(ref s) => s.as_bytes()
+ }
+ }
+}
+
+/*impl<'a> PartialEq for TextSlice<'a> {
+ fn eq(&self, rhs: &TextSlice<'a>) -> bool {
+ match (self, rhs) {
+ (&tsr(ref b), &tsr(ref c)) => b == c,
+ (&tsu(ref b), &tsu(ref c)) => b == c,
+ _ => false
+ }
+ }
+}
+
+impl PartialEq for Text {
+ fn eq(&self, rhs: &Text) -> bool {
+ match (self, rhs) {
+ (&tr(ref b), &tr(ref c)) => b == c,
+ (&tu(ref b), &tu(ref c)) => b == c,
+ _ => false
+ }
+ }
+}*/
+
+pub fn encoding(s: &str) -> Option<EncodingRef> {
+ encodings().into_iter().cloned().find(|e| e.name() == s)
+}
+
+pub fn lossy_decode(b: &[u8], e: EncodingRef) -> String {
+ e.decode(b, DecoderTrap::Replace)
+ .ok().expect("Shouldn't error with replacing trap")
+}
+
+pub fn def_lossy_decode(b: &[u8]) -> String {
+ lossy_decode(b, ::ENCODING)
+}