Separated reading and writing once more, thanks to changes in
rust-openssl.
This commit is contained in:
parent
5d72f0b41a
commit
40d8f09528
4 changed files with 122 additions and 149 deletions
|
@ -1,7 +1,7 @@
|
|||
[package]
|
||||
|
||||
name = "irc"
|
||||
version = "0.3.2"
|
||||
version = "0.4.0"
|
||||
description = "A simple, thread-safe IRC client library."
|
||||
authors = ["Aaron Weiss <aaronweiss74@gmail.com>"]
|
||||
license = "Unlicense"
|
||||
|
@ -22,5 +22,5 @@ optional = true
|
|||
|
||||
[dependencies.openssl]
|
||||
|
||||
openssl = "~0.2.1"
|
||||
openssl = "~0.2.2"
|
||||
optional = true
|
||||
|
|
147
src/conn.rs
147
src/conn.rs
|
@ -1,25 +1,29 @@
|
|||
//! Thread-safe connections on IrcStreams.
|
||||
#![experimental]
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
use std::io::{BufferedStream, IoResult, MemWriter, TcpStream};
|
||||
use std::io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
|
||||
#[cfg(any(feature = "encode", feature = "ssl"))] use std::io::{IoError, IoErrorKind};
|
||||
#[cfg(feature = "encode")] use encoding::{DecoderTrap, EncoderTrap, Encoding};
|
||||
#[cfg(feature = "encode")] use encoding::label::encoding_from_whatwg_label;
|
||||
use data::kinds::{IrcReader, IrcStream, IrcWriter};
|
||||
use data::kinds::{IrcReader, IrcWriter};
|
||||
use data::message::Message;
|
||||
#[cfg(feature = "ssl")] use openssl::ssl::{SslContext, SslStream, Tlsv1};
|
||||
#[cfg(feature = "ssl")] use openssl::ssl::error::SslError;
|
||||
|
||||
/// A thread-safe connection.
|
||||
#[experimental]
|
||||
pub struct Connection<T> where T: IrcStream {
|
||||
stream: Mutex<T>
|
||||
pub struct Connection<T: IrcReader, U: IrcWriter> {
|
||||
reader: Mutex<T>,
|
||||
writer: Mutex<U>,
|
||||
}
|
||||
|
||||
impl Connection<BufferedStream<TcpStream>> {
|
||||
/// A Connection over a buffered NetStream.
|
||||
pub type NetConnection = Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>>;
|
||||
|
||||
impl Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
|
||||
/// Creates a thread-safe TCP connection to the specified server.
|
||||
#[experimental]
|
||||
pub fn connect(host: &str, port: u16) -> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
pub fn connect(host: &str, port: u16) -> IoResult<NetConnection> {
|
||||
Connection::connect_internal(host, port, None)
|
||||
}
|
||||
|
||||
|
@ -27,23 +31,26 @@ impl Connection<BufferedStream<TcpStream>> {
|
|||
/// milliseconds.
|
||||
#[experimental]
|
||||
pub fn connect_with_timeout(host: &str, port: u16, timeout_ms: u64)
|
||||
-> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
-> IoResult<NetConnection> {
|
||||
Connection::connect_internal(host, port, Some(timeout_ms))
|
||||
}
|
||||
|
||||
/// Creates a thread-safe TCP connection with an optional timeout.
|
||||
#[experimental]
|
||||
fn connect_internal(host: &str, port: u16, timeout_ms: Option<u64>)
|
||||
-> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
-> IoResult<NetConnection> {
|
||||
let mut socket = try!(TcpStream::connect(format!("{}:{}", host, port)[]));
|
||||
socket.set_timeout(timeout_ms);
|
||||
Ok(Connection::new(BufferedStream::new(NetStream::UnsecuredTcpStream(socket))))
|
||||
Ok(Connection::new(
|
||||
BufferedReader::new(NetStream::UnsecuredTcpStream(socket.clone())),
|
||||
BufferedWriter::new(NetStream::UnsecuredTcpStream(socket))
|
||||
))
|
||||
}
|
||||
|
||||
/// Creates a thread-safe TCP connection to the specified server over SSL.
|
||||
/// If the library is compiled without SSL support, this method panics.
|
||||
#[experimental]
|
||||
pub fn connect_ssl(host: &str, port: u16) -> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
pub fn connect_ssl(host: &str, port: u16) -> IoResult<NetConnection> {
|
||||
Connection::connect_ssl_internal(host, port, None)
|
||||
}
|
||||
|
||||
|
@ -51,7 +58,7 @@ impl Connection<BufferedStream<TcpStream>> {
|
|||
/// in milliseconds. If the library is compiled without SSL support, this method panics.
|
||||
#[experimental]
|
||||
pub fn connect_ssl_with_timeout(host: &str, port: u16, timeout_ms: u64)
|
||||
-> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
-> IoResult<NetConnection> {
|
||||
Connection::connect_ssl_internal(host, port, Some(timeout_ms))
|
||||
}
|
||||
|
||||
|
@ -59,7 +66,7 @@ impl Connection<BufferedStream<TcpStream>> {
|
|||
#[experimental]
|
||||
#[cfg(not(feature = "ssl"))]
|
||||
fn connect_ssl_internal(host: &str, port: u16, _: Option<u64>)
|
||||
-> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
-> IoResult<NetConnection> {
|
||||
panic!("Cannot connect to {}:{} over SSL without compiling with SSL support.", host, port)
|
||||
}
|
||||
|
||||
|
@ -67,21 +74,25 @@ impl Connection<BufferedStream<TcpStream>> {
|
|||
#[experimental]
|
||||
#[cfg(feature = "ssl")]
|
||||
fn connect_ssl_internal(host: &str, port: u16, timeout_ms: Option<u64>)
|
||||
-> IoResult<Connection<BufferedStream<NetStream>>> {
|
||||
-> IoResult<NetConnection> {
|
||||
let mut socket = try!(TcpStream::connect(format!("{}:{}", host, port)[]));
|
||||
socket.set_timeout(timeout_ms);
|
||||
let ssl = try!(ssl_to_io(SslContext::new(Tlsv1)));
|
||||
let ssl_socket = try!(ssl_to_io(SslStream::new(&ssl, socket)));
|
||||
Ok(Connection::new(BufferedStream::new(NetStream::SslTcpStream(ssl_socket))))
|
||||
Ok(Connection::new(
|
||||
BufferedReader::new(NetStream::SslTcpStream(ssl_socket.clone())),
|
||||
BufferedWriter::new(NetStream::SslTcpSteram(ssl_socket)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IrcStream> Connection<T> {
|
||||
/// Creates a new connection from any arbitrary IrcStream.
|
||||
impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
|
||||
/// Creates a new connection from an IrcReader and an IrcWriter.
|
||||
#[experimental]
|
||||
pub fn new(stream: T) -> Connection<T> {
|
||||
pub fn new(reader: T, writer: U) -> Connection<T, U> {
|
||||
Connection {
|
||||
stream: Mutex::new(stream),
|
||||
reader: Mutex::new(reader),
|
||||
writer: Mutex::new(writer),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,18 +116,18 @@ impl<T: IrcStream> Connection<T> {
|
|||
detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
|
||||
})
|
||||
};
|
||||
let mut stream = self.stream.lock();
|
||||
try!(stream.write(data[]));
|
||||
stream.flush()
|
||||
let mut writer = self.writer.lock();
|
||||
try!(writer.write(data[]));
|
||||
writer.flush()
|
||||
}
|
||||
|
||||
/// Sends a message over this connection.
|
||||
#[experimental]
|
||||
#[cfg(not(feature = "encode"))]
|
||||
pub fn send(&self, message: Message) -> IoResult<()> {
|
||||
let mut stream = self.stream.lock();
|
||||
try!(stream.write_str(message.into_string()[]));
|
||||
stream.flush()
|
||||
let mut writer = self.writer.lock();
|
||||
try!(writer.write_str(message.into_string()[]));
|
||||
writer.flush()
|
||||
}
|
||||
|
||||
/// Receives a single line from this connection.
|
||||
|
@ -131,7 +142,7 @@ impl<T: IrcStream> Connection<T> {
|
|||
detail: Some(format!("Invalid decoder: {}", encoding))
|
||||
})
|
||||
};
|
||||
self.stream.lock().read_until(b'\n').and_then(|line|
|
||||
self.reader.lock().read_until(b'\n').and_then(|line|
|
||||
match encoding.decode(line[], DecoderTrap::Strict) {
|
||||
Ok(data) => Ok(data),
|
||||
Err(data) => Err(IoError {
|
||||
|
@ -147,13 +158,19 @@ impl<T: IrcStream> Connection<T> {
|
|||
#[experimental]
|
||||
#[cfg(not(feature = "encoding"))]
|
||||
pub fn recv(&self) -> IoResult<String> {
|
||||
self.stream.lock().read_line()
|
||||
self.reader.lock().read_line()
|
||||
}
|
||||
|
||||
/// Acquires the Stream lock.
|
||||
/// Acquires the Reader lock.
|
||||
#[experimental]
|
||||
pub fn stream<'a>(&'a self) -> MutexGuard<'a, T> {
|
||||
self.stream.lock()
|
||||
pub fn reader<'a>(&'a self) -> MutexGuard<'a, T> {
|
||||
self.reader.lock()
|
||||
}
|
||||
|
||||
/// Acquires the Writer lock.
|
||||
#[experimental]
|
||||
pub fn writer<'a>(&'a self) -> MutexGuard<'a, U> {
|
||||
self.writer.lock()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,53 +218,9 @@ impl Writer for NetStream {
|
|||
}
|
||||
}
|
||||
|
||||
/// An IrcStream built from an IrcWriter and an IrcReader.
|
||||
#[experimental]
|
||||
pub struct IoStream<T: IrcWriter, U: IrcReader> {
|
||||
writer: T,
|
||||
reader: U,
|
||||
}
|
||||
|
||||
impl<T: IrcWriter, U: IrcReader> IoStream<T, U> {
|
||||
/// Creates a new IoStream from the given IrcWriter and IrcReader.
|
||||
#[experimental]
|
||||
pub fn new(writer: T, reader: U) -> IoStream<T, U> {
|
||||
IoStream { writer: writer, reader: reader }
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: IrcReader> IoStream<MemWriter, U> {
|
||||
/// Gets the data contained in the MemWriter from this stream.
|
||||
pub fn value(&self) -> Vec<u8> {
|
||||
self.writer.get_ref().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IrcWriter, U: IrcReader> Buffer for IoStream<T, U> {
|
||||
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
|
||||
self.reader.fill_buf()
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: uint) {
|
||||
self.reader.consume(amt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IrcWriter, U: IrcReader> Reader for IoStream<T, U> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
|
||||
self.reader.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IrcWriter, U: IrcReader> Writer for IoStream<T, U> {
|
||||
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
|
||||
self.writer.write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Connection, IoStream};
|
||||
use super::Connection;
|
||||
use std::io::{MemReader, MemWriter};
|
||||
use std::io::util::{NullReader, NullWriter};
|
||||
use data::message::Message;
|
||||
|
@ -257,18 +230,18 @@ mod test {
|
|||
#[test]
|
||||
#[cfg(not(feature = "encode"))]
|
||||
fn send() {
|
||||
let conn = Connection::new(IoStream::new(MemWriter::new(), NullReader));
|
||||
let conn = Connection::new(NullReader, MemWriter::new());
|
||||
assert!(conn.send(
|
||||
Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("Testing!"))
|
||||
).is_ok());
|
||||
let data = String::from_utf8(conn.stream().value()).unwrap();
|
||||
let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
|
||||
assert_eq!(data[], "PRIVMSG test :Testing!\r\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "encode")]
|
||||
fn send_utf8() {
|
||||
let conn = Connection::new(IoStream::new(MemWriter::new(), NullReader));
|
||||
let conn = Connection::new(NullReader, MemWriter::new());
|
||||
assert!(conn.send(
|
||||
Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "l9"
|
||||
).is_ok());
|
||||
|
@ -285,33 +258,33 @@ mod test {
|
|||
#[test]
|
||||
#[cfg(not(feature = "encode"))]
|
||||
fn recv() {
|
||||
let conn = Connection::new(IoStream::new(
|
||||
NullWriter, MemReader::new("PRIVMSG test :Testing!\r\n".as_bytes().to_vec())
|
||||
));
|
||||
let conn = Connection::new(
|
||||
MemReader::new("PRIVMSG test :Testing!\r\n".as_bytes().to_vec()), NullWriter
|
||||
);
|
||||
assert_eq!(conn.recv().unwrap()[], "PRIVMSG test :Testing!\r\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "encode")]
|
||||
fn recv_utf8() {
|
||||
let conn = Connection::new(IoStream::new(
|
||||
NullWriter, MemReader::new(b"PRIVMSG test :Testing!\r\n".to_vec())
|
||||
));
|
||||
let conn = Connection::new(
|
||||
MemReader::new(b"PRIVMSG test :Testing!\r\n".to_vec()), NullWriter
|
||||
);
|
||||
assert_eq!(conn.recv("UTF-8").unwrap()[], "PRIVMSG test :Testing!\r\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "encode")]
|
||||
fn recv_iso885915() {
|
||||
let conn = Connection::new(IoStream::new(
|
||||
NullWriter, MemReader::new({
|
||||
let conn = Connection::new(
|
||||
MemReader::new({
|
||||
let mut vec = Vec::new();
|
||||
vec.push_all(b"PRIVMSG test :");
|
||||
vec.push_all(&[0xA4, 0xA6, 0xA8, 0xB4, 0xB8, 0xBC, 0xBD, 0xBE]);
|
||||
vec.push_all(b"\r\n");
|
||||
vec
|
||||
})
|
||||
));
|
||||
}), NullWriter
|
||||
);
|
||||
assert_eq!(conn.recv("l9").unwrap()[], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,59 +1,61 @@
|
|||
//! Interface for working with IRC Servers
|
||||
#![experimental]
|
||||
use std::collections::HashMap;
|
||||
use std::io::{BufferedStream, IoResult};
|
||||
use std::io::{BufferedReader, BufferedWriter, IoResult};
|
||||
use std::sync::Mutex;
|
||||
use conn::{Connection, NetStream};
|
||||
use data::{Command, Config, Message, Response, User};
|
||||
use data::Command::{JOIN, PONG};
|
||||
use data::kinds::IrcStream;
|
||||
use data::kinds::{IrcReader, IrcWriter};
|
||||
|
||||
pub mod utils;
|
||||
|
||||
/// Trait describing core Server functionality.
|
||||
#[experimental]
|
||||
pub trait Server<'a, T> {
|
||||
pub trait Server<'a, T, U> {
|
||||
/// Gets the configuration being used with this Server.
|
||||
fn config(&self) -> &Config;
|
||||
/// Sends a Command to this Server.
|
||||
fn send(&self, _: Command) -> IoResult<()>;
|
||||
/// Gets an Iterator over Messages received by this Server.
|
||||
fn iter(&'a self) -> ServerIterator<'a, T>;
|
||||
fn iter(&'a self) -> ServerIterator<'a, T, U>;
|
||||
/// Gets a list of Users in the specified channel.
|
||||
fn list_users(&self, _: &str) -> Option<Vec<User>>;
|
||||
}
|
||||
|
||||
/// A thread-safe implementation of an IRC Server connection.
|
||||
#[experimental]
|
||||
pub struct IrcServer<T> where T: IrcStream {
|
||||
pub struct IrcServer<T: IrcReader, U: IrcWriter> {
|
||||
/// The thread-safe IRC connection.
|
||||
conn: Connection<T>,
|
||||
conn: Connection<T, U>,
|
||||
/// The configuration used with this connection.
|
||||
config: Config,
|
||||
/// A thread-safe map of channels to the list of users in them.
|
||||
chanlists: Mutex<HashMap<String, Vec<User>>>,
|
||||
}
|
||||
|
||||
impl IrcServer<BufferedStream<NetStream>> {
|
||||
/// An IrcServer over a buffered NetStream.
|
||||
pub type NetIrcServer = IrcServer<BufferedReader<NetStream>, BufferedWriter<NetStream>>;
|
||||
|
||||
impl IrcServer<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
|
||||
/// Creates a new IRC Server connection from the configuration at the specified path,
|
||||
/// connecting immediately.
|
||||
#[experimental]
|
||||
pub fn new(config: &str) -> IoResult<IrcServer<BufferedStream<NetStream>>> {
|
||||
pub fn new(config: &str) -> IoResult<NetIrcServer> {
|
||||
IrcServer::from_config(try!(Config::load_utf8(config)))
|
||||
}
|
||||
|
||||
/// Creates a new IRC server connection from the configuration at the specified path with the
|
||||
/// specified timeout in milliseconds, connecting immediately.
|
||||
#[experimental]
|
||||
pub fn with_timeout(config: &str, timeout_ms: u64)
|
||||
-> IoResult<IrcServer<BufferedStream<NetStream>>> {
|
||||
pub fn with_timeout(config: &str, timeout_ms: u64) -> IoResult<NetIrcServer> {
|
||||
IrcServer::from_config_with_timeout(try!(Config::load_utf8(config)), timeout_ms)
|
||||
}
|
||||
|
||||
/// Creates a new IRC server connection from the specified configuration, connecting
|
||||
/// immediately.
|
||||
#[experimental]
|
||||
pub fn from_config(config: Config) -> IoResult<IrcServer<BufferedStream<NetStream>>> {
|
||||
pub fn from_config(config: Config) -> IoResult<NetIrcServer> {
|
||||
let conn = try!(if config.use_ssl {
|
||||
Connection::connect_ssl(config.server[], config.port)
|
||||
} else {
|
||||
|
@ -66,8 +68,7 @@ impl IrcServer<BufferedStream<NetStream>> {
|
|||
/// timeout in milliseconds, connecting
|
||||
/// immediately.
|
||||
#[experimental]
|
||||
pub fn from_config_with_timeout(config: Config, timeout_ms: u64)
|
||||
-> IoResult<IrcServer<BufferedStream<NetStream>>> {
|
||||
pub fn from_config_with_timeout(config: Config, timeout_ms: u64) -> IoResult<NetIrcServer> {
|
||||
let conn = try!(if config.use_ssl {
|
||||
Connection::connect_ssl_with_timeout(config.server[], config.port, timeout_ms)
|
||||
} else {
|
||||
|
@ -78,7 +79,7 @@ impl IrcServer<BufferedStream<NetStream>> {
|
|||
|
||||
}
|
||||
|
||||
impl<'a, T> Server<'a, T> for IrcServer<T> where T: IrcStream {
|
||||
impl<'a, T: IrcReader, U: IrcWriter> Server<'a, T, U> for IrcServer<T, U> {
|
||||
fn config(&self) -> &Config {
|
||||
&self.config
|
||||
}
|
||||
|
@ -93,7 +94,7 @@ impl<'a, T> Server<'a, T> for IrcServer<T> where T: IrcStream {
|
|||
self.conn.send(command.to_message())
|
||||
}
|
||||
|
||||
fn iter(&'a self) -> ServerIterator<'a, T> {
|
||||
fn iter(&'a self) -> ServerIterator<'a, T, U> {
|
||||
ServerIterator::new(self)
|
||||
}
|
||||
|
||||
|
@ -102,15 +103,15 @@ impl<'a, T> Server<'a, T> for IrcServer<T> where T: IrcStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> IrcServer<T> where T: IrcStream {
|
||||
impl<T: IrcReader, U: IrcWriter> IrcServer<T, U> {
|
||||
/// Creates an IRC server from the specified configuration, and any arbitrary Connection.
|
||||
#[experimental]
|
||||
pub fn from_connection(config: Config, conn: Connection<T>) -> IrcServer<T> {
|
||||
pub fn from_connection(config: Config, conn: Connection<T, U>) -> IrcServer<T, U> {
|
||||
IrcServer { conn: conn, config: config, chanlists: Mutex::new(HashMap::new()) }
|
||||
}
|
||||
|
||||
/// Gets a reference to the IRC server's connection.
|
||||
pub fn conn(&self) -> &Connection<T> {
|
||||
pub fn conn(&self) -> &Connection<T, U> {
|
||||
&self.conn
|
||||
}
|
||||
|
||||
|
@ -170,14 +171,14 @@ impl<T> IrcServer<T> where T: IrcStream {
|
|||
|
||||
/// An Iterator over an IrcServer's incoming Messages.
|
||||
#[experimental]
|
||||
pub struct ServerIterator<'a, T> where T: IrcStream {
|
||||
server: &'a IrcServer<T>
|
||||
pub struct ServerIterator<'a, T: IrcReader, U: IrcWriter> {
|
||||
server: &'a IrcServer<T, U>
|
||||
}
|
||||
|
||||
impl<'a, T> ServerIterator<'a, T> where T: IrcStream {
|
||||
impl<'a, T: IrcReader, U: IrcWriter> ServerIterator<'a, T, U> {
|
||||
/// Creates a new ServerIterator for the desired IrcServer.
|
||||
#[experimental]
|
||||
pub fn new(server: &IrcServer<T>) -> ServerIterator<T> {
|
||||
pub fn new(server: &IrcServer<T, U>) -> ServerIterator<T, U> {
|
||||
ServerIterator {
|
||||
server: server
|
||||
}
|
||||
|
@ -196,7 +197,7 @@ impl<'a, T> ServerIterator<'a, T> where T: IrcStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator<Message> for ServerIterator<'a, T> where T: IrcStream {
|
||||
impl<'a, T: IrcReader, U: IrcWriter> Iterator<Message> for ServerIterator<'a, T, U> {
|
||||
fn next(&mut self) -> Option<Message> {
|
||||
match self.get_next_line() {
|
||||
Err(_) => None,
|
||||
|
@ -215,7 +216,7 @@ mod test {
|
|||
use std::collections::HashMap;
|
||||
use std::io::{MemReader, MemWriter};
|
||||
use std::io::util::{NullReader, NullWriter};
|
||||
use conn::{Connection, IoStream};
|
||||
use conn::Connection;
|
||||
use data::{Config, User};
|
||||
use data::command::Command::PRIVMSG;
|
||||
use data::kinds::IrcReader;
|
||||
|
@ -254,9 +255,8 @@ mod test {
|
|||
}
|
||||
|
||||
|
||||
pub fn get_server_value<U>(server: IrcServer<IoStream<MemWriter, U>>) -> String
|
||||
where U: IrcReader {
|
||||
String::from_utf8(server.conn().stream().value()).unwrap()
|
||||
pub fn get_server_value<T: IrcReader>(server: IrcServer<T, MemWriter>) -> String {
|
||||
String::from_utf8((*server.conn().writer().deref()).get_ref().to_vec()).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -264,7 +264,7 @@ mod test {
|
|||
let exp = "PRIVMSG test :Hi!\r\nPRIVMSG test :This is a test!\r\n\
|
||||
:test!test@test JOIN #test\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(NullWriter, MemReader::new(exp.as_bytes().to_vec()))
|
||||
MemReader::new(exp.as_bytes().to_vec()), NullWriter
|
||||
));
|
||||
let mut messages = String::new();
|
||||
for message in server.iter() {
|
||||
|
@ -277,7 +277,7 @@ mod test {
|
|||
fn handle_message() {
|
||||
let value = "PING :irc.test.net\r\n:irc.test.net 376 test :End of /MOTD command.\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(MemWriter::new(), MemReader::new(value.as_bytes().to_vec()))
|
||||
MemReader::new(value.as_bytes().to_vec()), MemWriter::new()
|
||||
));
|
||||
for message in server.iter() {
|
||||
println!("{}", message);
|
||||
|
@ -289,7 +289,7 @@ mod test {
|
|||
#[test]
|
||||
fn send() {
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(MemWriter::new(), NullReader)
|
||||
NullReader, MemWriter::new()
|
||||
));
|
||||
assert!(server.send(PRIVMSG("#test", "Hi there!")).is_ok());
|
||||
assert_eq!(get_server_value(server)[],
|
||||
|
@ -300,7 +300,7 @@ mod test {
|
|||
fn user_tracking_names() {
|
||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(NullWriter, MemReader::new(value.as_bytes().to_vec()))
|
||||
MemReader::new(value.as_bytes().to_vec()), NullWriter
|
||||
));
|
||||
for message in server.iter() {
|
||||
println!("{}", message);
|
||||
|
@ -314,7 +314,7 @@ mod test {
|
|||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
||||
:test2!test@test JOIN #test\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(NullWriter, MemReader::new(value.as_bytes().to_vec()))
|
||||
MemReader::new(value.as_bytes().to_vec()), NullWriter
|
||||
));
|
||||
for message in server.iter() {
|
||||
println!("{}", message);
|
||||
|
@ -328,7 +328,7 @@ mod test {
|
|||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
||||
:owner!test@test PART #test\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(NullWriter, MemReader::new(value.as_bytes().to_vec()))
|
||||
MemReader::new(value.as_bytes().to_vec()), NullWriter
|
||||
));
|
||||
for message in server.iter() {
|
||||
println!("{}", message);
|
||||
|
@ -342,7 +342,7 @@ mod test {
|
|||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
||||
:test!test@test MODE #test +o test\r\n";
|
||||
let server = IrcServer::from_connection(test_config(), Connection::new(
|
||||
IoStream::new(NullWriter, MemReader::new(value.as_bytes().to_vec()))
|
||||
MemReader::new(value.as_bytes().to_vec()), NullWriter
|
||||
));
|
||||
for message in server.iter() {
|
||||
println!("{}", message);
|
||||
|
|
|
@ -5,17 +5,17 @@ use std::io::IoResult;
|
|||
use data::{Command, Config, User};
|
||||
use data::command::Command::{INVITE, JOIN, KILL, MODE, NICK, NOTICE, KICK};
|
||||
use data::command::Command::{OPER, PONG, PRIVMSG, SAMODE, SANICK, TOPIC, USER};
|
||||
use data::kinds::IrcStream;
|
||||
use data::kinds::{IrcReader, IrcWriter};
|
||||
use server::{Server, ServerIterator};
|
||||
|
||||
/// Functionality-providing wrapper for Server.
|
||||
/// Wrappers are currently not thread-safe, and should be created per-thread, as needed.
|
||||
#[experimental]
|
||||
pub struct Wrapper<'a, T> where T: IrcStream {
|
||||
server: &'a (Server<'a, T> + 'a)
|
||||
pub struct Wrapper<'a, T: IrcReader, U: IrcWriter> {
|
||||
server: &'a (Server<'a, T, U> + 'a)
|
||||
}
|
||||
|
||||
impl<'a, T> Server<'a, T> for Wrapper<'a, T> where T: IrcStream {
|
||||
impl<'a, T: IrcReader, U: IrcWriter> Server<'a, T, U> for Wrapper<'a, T, U> {
|
||||
fn config(&self) -> &Config {
|
||||
self.server.config()
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ impl<'a, T> Server<'a, T> for Wrapper<'a, T> where T: IrcStream {
|
|||
self.server.send(command)
|
||||
}
|
||||
|
||||
fn iter(&'a self) -> ServerIterator<'a, T> {
|
||||
fn iter(&'a self) -> ServerIterator<'a, T, U> {
|
||||
self.server.iter()
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,10 @@ impl<'a, T> Server<'a, T> for Wrapper<'a, T> where T: IrcStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Wrapper<'a, T> where T: IrcStream {
|
||||
impl<'a, T: IrcReader, U: IrcWriter> Wrapper<'a, T, U> {
|
||||
/// Creates a new Wrapper from the given Server.
|
||||
#[experimental]
|
||||
pub fn new(server: &'a Server<'a, T>) -> Wrapper<'a, T> {
|
||||
pub fn new(server: &'a Server<'a, T, U>) -> Wrapper<'a, T, U> {
|
||||
Wrapper { server: server }
|
||||
}
|
||||
|
||||
|
@ -152,14 +152,14 @@ mod test {
|
|||
use super::Wrapper;
|
||||
use std::io::MemWriter;
|
||||
use std::io::util::NullReader;
|
||||
use conn::{Connection, IoStream};
|
||||
use conn::Connection;
|
||||
use server::IrcServer;
|
||||
use server::test::{get_server_value, test_config};
|
||||
|
||||
#[test]
|
||||
fn identify() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.identify().unwrap();
|
||||
|
@ -171,7 +171,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_pong() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_pong("irc.test.net").unwrap();
|
||||
|
@ -183,7 +183,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_join() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_join("#test,#test2,#test3").unwrap();
|
||||
|
@ -195,7 +195,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_oper() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_oper("test", "test").unwrap();
|
||||
|
@ -207,7 +207,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_privmsg() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_privmsg("#test", "Hi, everybody!").unwrap();
|
||||
|
@ -219,7 +219,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_notice() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_notice("#test", "Hi, everybody!").unwrap();
|
||||
|
@ -231,7 +231,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_topic_no_topic() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_topic("#test", "").unwrap();
|
||||
|
@ -243,7 +243,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_topic() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_topic("#test", "Testing stuff.").unwrap();
|
||||
|
@ -255,7 +255,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_kill() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_kill("test", "Testing kills.").unwrap();
|
||||
|
@ -267,7 +267,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_kick_no_message() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_kick("#test", "test", "").unwrap();
|
||||
|
@ -279,7 +279,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_kick() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_kick("#test", "test", "Testing kicks.").unwrap();
|
||||
|
@ -291,7 +291,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_mode_no_modeparams() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_mode("#test", "+i", "").unwrap();
|
||||
|
@ -303,7 +303,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_mode() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_mode("#test", "+o", "test").unwrap();
|
||||
|
@ -315,7 +315,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_samode_no_modeparams() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_samode("#test", "+i", "").unwrap();
|
||||
|
@ -327,7 +327,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_samode() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_samode("#test", "+o", "test").unwrap();
|
||||
|
@ -339,7 +339,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_sanick() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_sanick("test", "test2").unwrap();
|
||||
|
@ -351,7 +351,7 @@ mod test {
|
|||
#[test]
|
||||
fn send_invite() {
|
||||
let server = IrcServer::from_connection(test_config(),
|
||||
Connection::new(IoStream::new(MemWriter::new(), NullReader)));
|
||||
Connection::new(NullReader, MemWriter::new()));
|
||||
{
|
||||
let wrapper = Wrapper::new(&server);
|
||||
wrapper.send_invite("test", "#test").unwrap();
|
||||
|
|
Loading…
Add table
Reference in a new issue