summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-09-08 11:35:02 -0400
committerJesse Luehrs <doy@tozt.net>2014-09-08 11:46:05 -0400
commitcb035e9de40b5b1e5a8a5e862ae9dd6a9da68d06 (patch)
treecb942997caf0ded2d4030d51e901a8579f3c45a4
parentcdf1047eb2c2d842006d7a117ad17845714ae004 (diff)
downloadrust-irc-cb035e9de40b5b1e5a8a5e862ae9dd6a9da68d06.tar.gz
rust-irc-cb035e9de40b5b1e5a8a5e862ae9dd6a9da68d06.zip
move the client implementation to a trait
this will allow us to more easily allow adding hooks
-rw-r--r--examples/client.rs25
-rw-r--r--src/client.rs55
2 files changed, 46 insertions, 34 deletions
diff --git a/examples/client.rs b/examples/client.rs
index cf9f328..eb3d31a 100644
--- a/examples/client.rs
+++ b/examples/client.rs
@@ -1,10 +1,33 @@
extern crate irc;
use irc::constants::{Ping, Pong};
+use irc::Client;
+
+use std::io;
+
+struct 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 conn (&mut self) -> &mut io::BufferedStream<io::TcpStream> {
+ &mut self.conn
+ }
+ fn socket_name (&self) -> Option<&str> {
+ match self.socket_name {
+ Some(ref name) => Some(name.as_slice()),
+ None => None,
+ }
+ }
+}
fn main () {
let builder = irc::ClientBuilder::new("doytest", "chat.freenode.net");
- let client = builder.connect();
+ let client: ExampleClient = builder.connect();
client.run_loop_with(|client, m| {
println!("{}", m);
match *m.message_type() {
diff --git a/src/client.rs b/src/client.rs
index 1623b02..55f2277 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -3,7 +3,7 @@ use std::{io, str};
use constants::{Nick, Pass, User};
use message::Message;
-pub struct ClientBuilder {
+pub struct ClientBuilder<T: Client> {
nick: String,
pass: Option<String>,
realname: String,
@@ -15,13 +15,8 @@ pub struct ClientBuilder {
port: u16,
}
-pub struct Client {
- conn: io::BufferedStream<io::TcpStream>,
- socket_name: Option<String>,
-}
-
-impl ClientBuilder {
- pub fn new (nick: &str, servername: &str) -> ClientBuilder {
+impl<T: Client> ClientBuilder<T> {
+ pub fn new (nick: &str, servername: &str) -> ClientBuilder<T> {
ClientBuilder {
nick: nick.to_string(),
pass: None,
@@ -35,32 +30,32 @@ impl ClientBuilder {
}
}
- pub fn set_pass (&mut self, pass: &str) -> &mut ClientBuilder {
+ pub fn set_pass (&mut self, pass: &str) -> &mut ClientBuilder<T> {
self.pass = Some(pass.to_string());
self
}
- pub fn set_username (&mut self, username: &str) -> &mut ClientBuilder {
+ pub fn set_username (&mut self, username: &str) -> &mut ClientBuilder<T> {
self.username = username.to_string();
self
}
- pub fn set_realname (&mut self, realname: &str) -> &mut ClientBuilder {
+ pub fn set_realname (&mut self, realname: &str) -> &mut ClientBuilder<T> {
self.realname = realname.to_string();
self
}
- pub fn set_hostname (&mut self, hostname: &str) -> &mut ClientBuilder {
+ pub fn set_hostname (&mut self, hostname: &str) -> &mut ClientBuilder<T> {
self.hostname = Some(hostname.to_string());
self
}
- pub fn set_port (&mut self, port: u16) -> &mut ClientBuilder {
+ pub fn set_port (&mut self, port: u16) -> &mut ClientBuilder<T> {
self.port = port;
self
}
- pub fn connect (self) -> Client {
+ pub fn connect (self) -> T {
let nick = self.nick.clone();
let pass = self.pass.clone();
let hostname = self.hostname.clone();
@@ -74,7 +69,7 @@ impl ClientBuilder {
Some(host) => host,
None => {
match client.socket_name() {
- Some(host) => host.to_string(),
+ Some(ref host) => host.to_string(),
// XXX something better here?
None => "localhost".to_string(),
}
@@ -98,40 +93,34 @@ impl ClientBuilder {
client
}
- pub fn connect_raw (self) -> 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 {
- conn: io::BufferedStream::new(stream),
- socket_name: socket_name,
- }
+ Client::new(io::BufferedStream::new(stream), socket_name)
}
}
-impl Client {
- pub fn read (&mut self) -> Message {
+pub trait Client {
+ fn new (conn: io::BufferedStream<io::TcpStream>, socket_name: Option<String>) -> Self;
+ fn conn (&mut self) -> &mut io::BufferedStream<io::TcpStream>;
+ fn socket_name (&self) -> Option<&str>;
+
+ fn read (&mut self) -> Message {
// \n isn't valid inside a message, so this should be fine. if the \n
// we find isn't preceded by a \r, this will be caught by the message
// parser.
- let buf = self.conn.read_until(b'\n');
+ let buf = self.conn().read_until(b'\n');
// XXX handle different encodings
// XXX proper error handling
Message::parse(str::from_utf8(buf.unwrap().as_slice()).unwrap()).unwrap()
}
- pub fn write (&mut self, msg: Message) {
- msg.write_protocol_string(&mut self.conn);
- }
-
- pub fn socket_name (&self) -> Option<&str> {
- match self.socket_name {
- Some(ref name) => Some(name.as_slice()),
- None => None,
- }
+ fn write (&mut self, msg: Message) {
+ msg.write_protocol_string(self.conn());
}
// XXX eventually, we'll want to set up callbacks for specific events
@@ -140,7 +129,7 @@ impl Client {
// 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
- pub fn run_loop_with (mut self, handler: |&mut Client, Message|) {
+ fn run_loop_with (mut self, handler: |&mut Self, Message|) {
loop {
let m = self.read();
handler(&mut self, m);