aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTill Hoeppner2015-06-17 17:03:56 +0200
committerTill Hoeppner2015-06-17 17:04:06 +0200
commit2902d8734f5c1f036eb340e35e8d1dc7a74c23b6 (patch)
treed09ff702397a73c66c938b5891765e92e18abd69 /src
parent63838165c31397fec199bf99c96497a1169c4d52 (diff)
downloadirsc-2902d8734f5c1f036eb340e35e8d1dc7a74c23b6.tar.gz
irsc-2902d8734f5c1f036eb340e35e8d1dc7a74c23b6.tar.xz
irsc-2902d8734f5c1f036eb340e35e8d1dc7a74c23b6.zip
This commit is a little too large. Sorry. :S
Diffstat (limited to 'src')
-rw-r--r--src/client.rs75
-rw-r--r--src/event.rs9
-rw-r--r--src/lib.rs16
-rw-r--r--src/message.rs2
4 files changed, 80 insertions, 22 deletions
diff --git a/src/client.rs b/src/client.rs
index e573596..d830e1e 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -11,6 +11,9 @@ use std::borrow::Cow;
use message::Message;
use command::Command;
+use command::Command::*;
+use reply::Reply;
+use event::Event;
use ::{ DEBUG, Result, IrscError };
#[cfg(feature = "ssl")]
@@ -64,35 +67,38 @@ impl Client {
fn handle_event(&mut self, msg: &Message) {
let _ = match Command::from_message(msg) {
- Some(Command::PING(s1, s2)) => self.send(Command::PONG(s1, s2)),
- _ => Ok(())
+ Some(PING(s1, s2)) => self.send(PONG(s1, s2)),
+ _ => Result(Ok(()))
};
}
- pub fn connect(&mut self, host: String, port: u16) -> Result<()> {
+ pub fn connect(&mut self, host: &str, port: u16) -> Result<()> {
let s = &mut self.stream;
- match *s { Some(_) => return Err(IrscError::AlreadyConnected), _ => () };
- *s = match TcpStream::connect((host.as_ref(), port)) {
+ if s.is_some() { return Result(Err(IrscError::AlreadyConnected)) }
+ *s = match TcpStream::connect((host, port)) {
Ok(tcp) => Some(StreamKind::Plain(tcp)),
- Err(e) => return Err(IrscError::Io(e))
+ Err(e) => return Result(Err(IrscError::Io(e)))
};
- Ok(())
+ Result(Ok(()))
}
#[cfg(feature = "ssl")]
- pub fn connect_ssl(&mut self, host: String, port: u16, ssl: Ssl) -> Result<()> {
+ pub fn connect_ssl(&mut self, host: &str, port: u16, ssl: Ssl) -> Result<()> {
let s = &mut self.stream;
- match *s { Some(_) => return Err(IrscError::AlreadyConnected), _ => () };
- let tcp_stream = match TcpStream::connect((host.as_ref(), port)) {
+ if s.is_some() { return Result(Err(IrscError::AlreadyConnected)) };
+ let tcp_stream = match TcpStream::connect((host, port)) {
Ok(tcp) => Some(tcp),
- Err(e) => return Err(IrscError::Io(e))
+ Err(e) => return Result(Err(IrscError::Io(e)))
};
match tcp_stream.map(|tcp| SslStream::new_from(ssl, tcp)) {
- Some(Ok(ssl_stream)) => { *s = Some(StreamKind::Ssl(ssl_stream)); Ok(()) },
- Some(Err(ssl_error)) => Err(IrscError::Ssl(ssl_error)),
- None => Err(IrscError::NotConnected)
+ Some(Ok(ssl_stream)) => {
+ *s = Some(StreamKind::Ssl(ssl_stream));
+ Result(Ok(()))
+ },
+ Some(Err(ssl_error)) => Result(Err(IrscError::Ssl(ssl_error))),
+ None => Result(Err(IrscError::NotConnected))
}
}
@@ -103,11 +109,11 @@ impl Client {
panic!("Message too long, kittens will die if this runs in release mode. Msg: {}", s)
}
- self.stream.as_mut()
+ Result(self.stream.as_mut()
.ok_or(IrscError::NotConnected)
.and_then(|mut stream| stream.write_all(s.as_bytes())
.and_then(|_| stream.flush())
- .map_err(IrscError::Io))
+ .map_err(IrscError::Io)))
}
pub fn send_message(&mut self, msg: Message) -> Result<()> {
@@ -118,13 +124,13 @@ impl Client {
self.send_message(cmd.to_message())
}
- pub fn listen<F>(&mut self, events: F) -> Result<()>
- where F: Fn(&mut Client, &Message) {
+ pub fn 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()),
#[cfg(feature = "ssl")]
Some(StreamKind::Ssl(ref s)) => StreamKind::Ssl((*s).try_clone().unwrap()),
- None => return Err(IrscError::NotConnected)
+ None => return Result(Err(IrscError::NotConnected))
});
for line in reader.lines() {
@@ -132,9 +138,36 @@ impl Client {
if let Ok(msg) = line {
self.handle_event(&msg);
- events(self, &msg);
+
+ // If a callback is desired, try to parse the message
+ // into a Command or a Reply, and call back.
+ if let Some(ref on_event) = events {
+ let event = match Command::from_message(&msg) {
+ Some(m) => Some(Event::Command(m)),
+ None => match Reply::from_message(&msg) {
+ Some(r) => Some(Event::Reply(r)),
+ None => None
+ }
+ };
+
+ on_event(self, &msg, event);
+ }
}
}
- Ok(())
+ Result(Ok(()))
+ }
+
+ 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())
+ }
+
+ pub fn msg(&mut self, to: &str, message: &str) -> Result<()> {
+ self.send_message(PRIVMSG(to.into(), message.into()).to_message())
+ }
+
+ 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()))
+
}
}
diff --git a/src/event.rs b/src/event.rs
new file mode 100644
index 0000000..70ec816
--- /dev/null
+++ b/src/event.rs
@@ -0,0 +1,9 @@
+use command;
+use reply;
+
+pub enum Event<'a> {
+ Command(command::Command<'a>),
+ Reply(reply::Reply<'a>),
+ Connected,
+ Disconnected
+}
diff --git a/src/lib.rs b/src/lib.rs
index abcbc50..168f137 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,9 +18,11 @@ pub mod callback;
pub mod message;
pub mod command;
pub mod reply;
+pub mod event;
use std::io;
use std::result;
+use std::ops::{ Deref, DerefMut };
#[cfg(feature = "ssl")]
use openssl::ssl::error::SslError;
@@ -29,6 +31,7 @@ pub use ident::Ident;
pub use message::{ Message, MsgType };
pub use command::Command;
pub use reply::Reply;
+pub use event::Event;
pub use client::Client;
#[derive(Debug)]
@@ -46,6 +49,17 @@ impl From<SslError> for IrscError {
fn from(e: SslError) -> IrscError { IrscError::Ssl(e) }
}
-pub type Result<T> = result::Result<T, IrscError>;
+pub struct Result<T>(result::Result<T, IrscError>);
+
+impl<T> Deref for Result<T> {
+ type Target = result::Result<T, IrscError>;
+ fn deref(&self) -> &result::Result<T, IrscError> { &self.0 }
+}
+
+impl<T> DerefMut for Result<T> {
+ fn deref_mut(&mut self) -> &mut result::Result<T, IrscError> { &mut self.0 }
+}
+
+impl<T> Result<T> { fn inner(self) -> result::Result<T, IrscError> { self.0 } }
pub const DEBUG: bool = cfg!(debug_assertions);
diff --git a/src/message.rs b/src/message.rs
index dd88b1f..8b897be 100644
--- a/src/message.rs
+++ b/src/message.rs
@@ -6,6 +6,7 @@ use std::borrow::{ ToOwned };
use std::ops::{ Deref, Range };
use ::IrscError;
+use ident::Ident;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MsgType {
@@ -92,6 +93,7 @@ impl Message {
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 {