summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-09-08 12:31:27 -0400
committerJesse Luehrs <doy@tozt.net>2014-09-08 12:31:27 -0400
commite41c5fa768cd006fc35ae14d7f6dec7912462161 (patch)
tree0399d5dc9e3a8b310474a5273a37f345534d9bd3
parent318259f54ee614d56aab0f434606a990645eee42 (diff)
downloadrust-irc-e41c5fa768cd006fc35ae14d7f6dec7912462161.tar.gz
rust-irc-e41c5fa768cd006fc35ae14d7f6dec7912462161.zip
start moving things into callbacks
-rw-r--r--examples/client.rs22
-rw-r--r--src/client.rs103
2 files changed, 70 insertions, 55 deletions
diff --git a/examples/client.rs b/examples/client.rs
index 6696460..4da1220 100644
--- a/examples/client.rs
+++ b/examples/client.rs
@@ -6,13 +6,17 @@ use irc::Client;
use std::io;
struct ExampleClient {
+ builder: irc::ClientBuilder<ExampleClient>,
conn: io::BufferedStream<io::TcpStream>,
socket_name: Option<String>,
}
impl irc::Client for ExampleClient {
- fn new (conn: io::BufferedStream<io::TcpStream>, socket_name: Option<String>) -> ExampleClient {
- ExampleClient { conn: conn, socket_name: socket_name }
+ fn new (builder: irc::ClientBuilder<ExampleClient>, conn: io::BufferedStream<io::TcpStream>, socket_name: Option<String>) -> ExampleClient {
+ ExampleClient { builder: builder, conn: conn, socket_name: socket_name }
+ }
+ fn builder (&self) -> &irc::ClientBuilder<ExampleClient> {
+ &self.builder
}
fn conn (&mut self) -> &mut io::BufferedStream<io::TcpStream> {
&mut self.conn
@@ -23,12 +27,8 @@ impl irc::Client for ExampleClient {
None => None,
}
}
-}
-fn main () {
- let builder = irc::ClientBuilder::new("doytest", "chat.freenode.net");
- let client: ExampleClient = builder.connect();
- client.run_loop_with(|client, m| {
+ fn on_message (client: &mut ExampleClient, m: irc::Message) {
print!("{}", m.to_protocol_string());
match *m.message_type() {
Ping => {
@@ -36,5 +36,11 @@ fn main () {
},
_ => {},
}
- });
+ }
+}
+
+fn main () {
+ let builder = irc::ClientBuilder::new("doytest", "chat.freenode.net");
+ let client: ExampleClient = builder.connect();
+ client.run_loop();
}
diff --git a/src/client.rs b/src/client.rs
index 55f2277..979d33b 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -56,56 +56,19 @@ impl<T: Client> ClientBuilder<T> {
}
pub fn connect (self) -> T {
- let nick = self.nick.clone();
- let pass = self.pass.clone();
- let hostname = self.hostname.clone();
- let username = self.username.clone();
- let servername = self.servername.clone();
- let realname = self.realname.clone();
-
- let mut client = self.connect_raw();
-
- let hostname = match hostname {
- Some(host) => host,
- None => {
- match client.socket_name() {
- Some(ref host) => host.to_string(),
- // XXX something better here?
- None => "localhost".to_string(),
- }
- },
- };
-
- match pass {
- Some(pass) => {
- client.write(Message::new(None, Pass, vec![pass]));
- },
- None => {},
- }
-
- client.write(Message::new(None, Nick, vec![nick]));
-
- client.write(
- Message::new(
- None, User, vec![ username, hostname, servername, realname ],
- )
- );
- client
- }
-
- pub fn connect_raw (self) -> T {
let mut stream = io::TcpStream::connect(self.servername.as_slice(), self.port);
let mut stream = stream.unwrap();
let socket_name = match stream.socket_name() {
Ok(addr) => Some(addr.ip.to_string()),
Err(_) => None,
};
- Client::new(io::BufferedStream::new(stream), socket_name)
+ Client::new(self, io::BufferedStream::new(stream), socket_name)
}
}
pub trait Client {
- fn new (conn: io::BufferedStream<io::TcpStream>, socket_name: Option<String>) -> Self;
+ fn new (builder: ClientBuilder<Self>, conn: io::BufferedStream<io::TcpStream>, socket_name: Option<String>) -> Self;
+ fn builder (&self) -> &ClientBuilder<Self>;
fn conn (&mut self) -> &mut io::BufferedStream<io::TcpStream>;
fn socket_name (&self) -> Option<&str>;
@@ -123,16 +86,62 @@ pub trait Client {
msg.write_protocol_string(self.conn());
}
- // XXX eventually, we'll want to set up callbacks for specific events
- // beforehand, and just have a `run_loop` method that loops and calls the
- // preset callbacks as necessary. unfortunately, rust doesn't handle
- // storing closures very well yet if they need to receive a borrowed
- // pointer, and we would need to pass the client object into the callback
- // in order to make this work
- fn run_loop_with (mut self, handler: |&mut Self, Message|) {
+ fn run_loop_with (mut self, handler: |&mut Self, Message|) -> Self {
loop {
let m = self.read();
handler(&mut self, m);
}
+ self
+ }
+
+ // XXX once storing closures in structs works, we'll also want to provide
+ // a default CallbackClient impl of Client to allow users to not have to
+ // worry about the struct layout for simple cases.
+ fn run_loop (mut self) {
+ Client::on_connect(&mut self);
+
+ let mut client = self.run_loop_with(|client, m| {
+ Client::on_message(client, m);
+ });
+
+ Client::on_disconnect(&mut client);
+ }
+
+ fn on_connect (client: &mut Self) {
+ let nick = client.builder().nick.clone();
+ let pass = client.builder().pass.clone();
+ let username = client.builder().username.clone();
+ let servername = client.builder().servername.clone();
+ let realname = client.builder().realname.clone();
+
+ match pass {
+ Some(pass) => {
+ client.write(Message::new(None, Pass, vec![pass]));
+ },
+ None => {},
+ }
+
+ client.write(Message::new(None, Nick, vec![nick]));
+
+ let hostname = match client.builder().hostname {
+ Some(ref host) => host.clone(),
+ None => {
+ match client.socket_name() {
+ Some(ref host) => host.to_string(),
+ // XXX something better here?
+ None => "localhost".to_string(),
+ }
+ },
+ };
+
+ client.write(
+ Message::new(
+ None, User, vec![ username, hostname, servername, realname ],
+ )
+ );
}
+
+ fn on_disconnect (client: &mut Self) { }
+
+ fn on_message (client: &mut Self, m: Message) { }
}