diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client.rs | 41 | ||||
-rw-r--r-- | src/command.rs | 276 | ||||
-rw-r--r-- | src/event.rs | 3 | ||||
-rw-r--r-- | src/reply.rs | 2 |
4 files changed, 314 insertions, 8 deletions
diff --git a/src/client.rs b/src/client.rs index d830e1e..55ec101 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,7 +7,9 @@ use std::io::{ }; use std::net::TcpStream; -use std::borrow::Cow; +use std::borrow::Cow::{ self, Borrowed, Owned }; + +//use carboxyl::{ Stream, Sink }; use message::Message; use command::Command; @@ -55,13 +57,15 @@ impl Read for StreamKind { } pub struct Client { - stream: Option<StreamKind> + stream: Option<StreamKind>, +// sink: Sink<Message> } impl Client { pub fn new() -> Client { Client { - stream: None + stream: None, +// sink: Sink::new() } } @@ -124,7 +128,7 @@ impl Client { self.send_message(cmd.to_message()) } - pub fn listen<F>(&mut self, events: Option<F>) -> Result<()> + fn intern_listen<F>(&mut self, events: Option<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()), @@ -152,11 +156,38 @@ impl Client { on_event(self, &msg, event); } + + //self.sink.send(msg) } } Result(Ok(())) } + pub fn listen(&mut self) -> Result<()> { + self.intern_listen::<fn(&mut Client, &Message, Option<Event>)>(None) + } + + pub fn listen_with_callback<F>(&mut self, events: F) -> Result<()> + where F: Fn(&mut Client, &Message, Option<Event>) { + self.intern_listen(Some(events)) + } + +// pub fn messages(&self) -> Stream<Message> { self.sink.stream() } + + /*pub fn events(&self) -> Stream<(Message, Event)> { + self.messages().filter_map(|msg| match Command::from_message(&msg) { + Some(m) => Some((msg, Event::Command(m.clone()))), + None => match Reply::from_message(&msg) { + Some(r) => Some((msg, Event::Reply(r))), + None => None + } + }) + }*/ + +// pub fn commands(&self) -> Stream<Command> { +// self.messages().filter_map(|msg| Command::from_message(&msg).map(|c| c.to_static())) +// } + pub 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()) } @@ -167,7 +198,7 @@ impl Client { pub fn register(&mut self, nick: &str, user: &str, desc: &str) -> Result<()> { Result(self.send_message(NICK(nick.into()).to_message()).inner() - .and_then(|_| self.send_message(USER(user.into(), Cow::Borrowed("0"), Cow::Borrowed("*"), desc.into()).to_message()).inner())) + .and_then(|_| self.send_message(USER(user.into(), Borrowed("0"), Borrowed("*"), desc.into()).to_message()).inner())) } } diff --git a/src/command.rs b/src/command.rs index 883db7e..08d07d5 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] -use std::borrow::{ Cow }; +use std::borrow::{ Cow, Borrow, ToOwned }; use std::borrow::Cow::*; use std::iter::Extend; @@ -8,7 +8,7 @@ use message::{ Message, MsgType }; pub type CS<'a> = Cow<'a, str>; -#[derive(Debug, Hash, PartialEq, Eq)] +#[derive(Debug, Hash, Clone, PartialEq, Eq)] #[doc(disables)] pub enum Command<'a> { /// ```text @@ -1579,6 +1579,143 @@ pub enum Command<'a> { USERHOST(Vec<CS<'a>>), } +/*impl<'a> Clone for Command<'a> { + fn clone(&self) -> Command<'a> { + use self::Command::*; + match self { + &PASS(ref pw) => PASS(pw.to_owned().clone()), + /*&NICK(ref nick) => + Message::format(None, Borrowed("NICK"), vec![], Some(nick.clone()), MsgType::Irc), + &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), + &OPER(ref name, ref pw) => + Message::format(None, Borrowed("OPER"), + vec![name.clone(), pw.clone()], None, MsgType::Irc), + &UMODE(ref mode) => + Message::format(None, Borrowed("MODE"), vec![], Some(mode.clone()), MsgType::Irc), + &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), + &QUIT(ref msg) => + Message::format(None, Borrowed("QUIT"), vec![], msg.clone(), MsgType::Irc), + &SQUIT(ref server, ref comment) => + Message::format(None, Borrowed("SQUIT"), + vec![server.clone()], Some(comment.clone()), MsgType::Irc), + &JOIN(ref ch, ref pw) => + Message::format(None, Borrowed("JOIN"), + vec![Owned(ch.connect(",")), Owned(pw.connect(","))], None, MsgType::Irc), + &PART(ref ch, ref reason) => + Message::format(None, Borrowed("PART"), + vec![Owned(ch.connect(","))], reason.clone(), MsgType::Irc), + &MODE(ref channel, ref modes) => + // Screw this, folding will have to do. + Message::format(None, Borrowed("MODE"), + modes.iter().fold(vec![channel.clone()], |mut v, &(ref a, ref b)| { + v.push(a.clone()); + v.push(b.clone()); + v + }), None, MsgType::Irc), + &TOPIC(ref channel, ref topic) => + Message::format(None, Borrowed("TOPIC"), + vec![channel.clone()], topic.clone(), MsgType::Irc), + &NAMES(ref ch, ref target) => + Message::format(None, Borrowed("NAMES"), + vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc), + &LIST(ref ch, ref target) => + Message::format(None, Borrowed("LIST"), + vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc), + &INVITE(ref nick, ref channel) => + Message::format(None, Borrowed("INVITE"), + vec![nick.clone()], Some(channel.clone()), MsgType::Irc), + &KICK(ref ch, ref users, ref comment) => + Message::format(None, Borrowed("KICK"), + vec![Owned(ch.connect(",")), Owned(users.connect(","))], + comment.clone(), MsgType::Irc), + &PRIVMSG(ref target, ref msg) => + Message::format(None, Borrowed("PRIVMSG"), + vec![target.clone()], Some(msg.clone()), MsgType::Irc), + &NOTICE(ref target, ref text) => + Message::format(None, Borrowed("NOTICE"), + vec![target.clone()], Some(text.clone()), MsgType::Irc), + &MOTD(ref target) => + Message::format(None, Borrowed("MOTD"), vec![], target.clone(), MsgType::Irc), + &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), + &VERSION(ref target) => + Message::format(None, Borrowed("VERSION"), vec![], target.clone(), MsgType::Irc), + &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), + &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), + &TIME(ref target) => + Message::format(None, Borrowed("TIME"), vec![], target.clone(), MsgType::Irc), + &CONNECT(ref server, ref port, ref remote) => + Message::format(None, Borrowed("CONNECT"), + vec![server.clone(), Owned(format!("{}", port))], remote.clone(), MsgType::Irc), + &TRACE(ref target) => + Message::format(None, Borrowed("TRACE"), vec![], target.clone(), MsgType::Irc), + &ADMIN(ref target) => + Message::format(None, Borrowed("ADMIN"), vec![], target.clone(), MsgType::Irc), + &INFO(ref target) => + Message::format(None, Borrowed("INFO"), vec![], target.clone(), MsgType::Irc), + &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), + &SQUERY(ref name, ref text) => + Message::format(None, Borrowed("SQUERY"), + vec![name.clone()], Some(text.clone()), MsgType::Irc), + &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), + &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), + &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), + &PING(ref s1, ref s2) => + Message::format(None, Borrowed("PING"), vec![s1.clone()], s2.clone(), MsgType::Irc), + &PONG(ref s1, ref s2) => + Message::format(None, Borrowed("PONG"), vec![s1.clone()], s2.clone(), MsgType::Irc), + */ /*&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) + }, + &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) + },*/ + _ => unimplemented!() + } + + } +}*/ + impl<'a> Command<'a> { pub fn from_message(msg: &'a Message) -> Option<Command<'a>> { use self::Command::*; @@ -1756,6 +1893,141 @@ impl<'a> Command<'a> { } } +/* pub fn to_static(&self) -> Command<'static> { + use self::Command::*; + match self { + &PASS(ref pw) => PASS(pw.to_owned().clone()), + /*&NICK(ref nick) => + Message::format(None, Borrowed("NICK"), vec![], Some(nick.clone()), MsgType::Irc), + &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), + &OPER(ref name, ref pw) => + Message::format(None, Borrowed("OPER"), + vec![name.clone(), pw.clone()], None, MsgType::Irc), + &UMODE(ref mode) => + Message::format(None, Borrowed("MODE"), vec![], Some(mode.clone()), MsgType::Irc), + &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), + &QUIT(ref msg) => + Message::format(None, Borrowed("QUIT"), vec![], msg.clone(), MsgType::Irc), + &SQUIT(ref server, ref comment) => + Message::format(None, Borrowed("SQUIT"), + vec![server.clone()], Some(comment.clone()), MsgType::Irc), + &JOIN(ref ch, ref pw) => + Message::format(None, Borrowed("JOIN"), + vec![Owned(ch.connect(",")), Owned(pw.connect(","))], None, MsgType::Irc), + &PART(ref ch, ref reason) => + Message::format(None, Borrowed("PART"), + vec![Owned(ch.connect(","))], reason.clone(), MsgType::Irc), + &MODE(ref channel, ref modes) => + // Screw this, folding will have to do. + Message::format(None, Borrowed("MODE"), + modes.iter().fold(vec![channel.clone()], |mut v, &(ref a, ref b)| { + v.push(a.clone()); + v.push(b.clone()); + v + }), None, MsgType::Irc), + &TOPIC(ref channel, ref topic) => + Message::format(None, Borrowed("TOPIC"), + vec![channel.clone()], topic.clone(), MsgType::Irc), + &NAMES(ref ch, ref target) => + Message::format(None, Borrowed("NAMES"), + vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc), + &LIST(ref ch, ref target) => + Message::format(None, Borrowed("LIST"), + vec![Owned(ch.connect(","))], target.clone(), MsgType::Irc), + &INVITE(ref nick, ref channel) => + Message::format(None, Borrowed("INVITE"), + vec![nick.clone()], Some(channel.clone()), MsgType::Irc), + &KICK(ref ch, ref users, ref comment) => + Message::format(None, Borrowed("KICK"), + vec![Owned(ch.connect(",")), Owned(users.connect(","))], + comment.clone(), MsgType::Irc), + &PRIVMSG(ref target, ref msg) => + Message::format(None, Borrowed("PRIVMSG"), + vec![target.clone()], Some(msg.clone()), MsgType::Irc), + &NOTICE(ref target, ref text) => + Message::format(None, Borrowed("NOTICE"), + vec![target.clone()], Some(text.clone()), MsgType::Irc), + &MOTD(ref target) => + Message::format(None, Borrowed("MOTD"), vec![], target.clone(), MsgType::Irc), + &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), + &VERSION(ref target) => + Message::format(None, Borrowed("VERSION"), vec![], target.clone(), MsgType::Irc), + &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), + &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), + &TIME(ref target) => + Message::format(None, Borrowed("TIME"), vec![], target.clone(), MsgType::Irc), + &CONNECT(ref server, ref port, ref remote) => + Message::format(None, Borrowed("CONNECT"), + vec![server.clone(), Owned(format!("{}", port))], remote.clone(), MsgType::Irc), + &TRACE(ref target) => + Message::format(None, Borrowed("TRACE"), vec![], target.clone(), MsgType::Irc), + &ADMIN(ref target) => + Message::format(None, Borrowed("ADMIN"), vec![], target.clone(), MsgType::Irc), + &INFO(ref target) => + Message::format(None, Borrowed("INFO"), vec![], target.clone(), MsgType::Irc), + &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), + &SQUERY(ref name, ref text) => + Message::format(None, Borrowed("SQUERY"), + vec![name.clone()], Some(text.clone()), MsgType::Irc), + &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), + &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), + &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), + &PING(ref s1, ref s2) => + Message::format(None, Borrowed("PING"), vec![s1.clone()], s2.clone(), MsgType::Irc), + &PONG(ref s1, ref s2) => + Message::format(None, Borrowed("PONG"), vec![s1.clone()], s2.clone(), MsgType::Irc), + */ /*&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) + }, + &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) + },*/ + _ => unimplemented!() + } + + }*/ + //pub fn is_reply(&self) -> bool { let i = *self as uint; i >= 200 && i <= 399 } //pub fn is_error(&self) -> bool { let i = *self as uint; i >= 400 && i <= 599 } } diff --git a/src/event.rs b/src/event.rs index 70ec816..488ac04 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,6 +1,9 @@ +use std::borrow::{ Borrow, ToOwned }; + use command; use reply; +#[derive(Debug, Clone, PartialEq)] pub enum Event<'a> { Command(command::Command<'a>), Reply(reply::Reply<'a>), diff --git a/src/reply.rs b/src/reply.rs index d1aad9d..f7c09e6 100644 --- a/src/reply.rs +++ b/src/reply.rs @@ -8,7 +8,7 @@ use ::message::{ MsgType, Message }; pub type CS<'a> = Cow<'a, str>; #[allow(non_camel_case_types)] -#[derive(Debug, Hash, PartialEq, Eq)] +#[derive(Debug, Hash, Clone, PartialEq, Eq)] pub enum Reply<'a> { /// 001 RPL_WELCOME /// "Welcome to the Internet Relay Network |