aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.rs41
-rw-r--r--src/command.rs276
-rw-r--r--src/event.rs3
-rw-r--r--src/reply.rs2
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